具有 const ref 参数的函数模板特化
Function template specialization with const ref arguments
下面的代码compiles fine.
#include <iostream>
struct rgb8{
uint8_t r() const {return 0;};
};
template<typename L, typename P>
L pixelToLevel(P p) {
return static_cast<L>(p);
}
template<>
uint8_t pixelToLevel<uint8_t, rgb8>(rgb8 p) { // <---------- line X
return pixelToLevel<uint8_t, uint8_t>(p.r());
}
int main()
{
pixelToLevel<uint8_t>(rgb8());
return 0;
}
但是如果我在第 X 行中将 rgb8 p
更改为 const rgb8& p
,它会编译失败。
(生成的确切编译器错误取决于显式模板参数 rgb8
是否也更改为 const rgb8&
。)
如果我想通过引用而不是 X 行中的值传递 p
,我该如何编译它?
您需要更改特化声明中的模板参数,以及调用它时的模板参数。否则将调用主模板。例如
template<>
uint8_t pixelToLevel<uint8_t, const rgb8&>(const rgb8& p) { // <---------- line X
return pixelToLevel<uint8_t, uint8_t>(p.r());
}
然后
pixelToLevel<uint8_t, const rgb8&>(rgb8());
编辑
给定 pixelToLevel<uint8_t>(rgb8());
,使用主模板执行模板参数推导,P
推导为 rgb8
(不会推导为当前主模板的 const rgb8&
模板的参数声明),则不会调用特化版本。
您可以应用重载而不是模板特化。例如
template<typename L, typename P>
L pixelToLevel(P p) {
return static_cast<L>(p);
}
template<typename L>
L pixelToLevel(const rgb8& p) { // <---------- line X
return pixelToLevel<L, uint8_t>(p.r());
}
然后 pixelToLevel<uint8_t>(rgb8());
会 select 第二次重载。
@songyuanyao 的另一种解决方案是
template<typename L, typename P>
L pixelToLevel(const P& p) {
return static_cast<L>(p);
}
下面的代码compiles fine.
#include <iostream>
struct rgb8{
uint8_t r() const {return 0;};
};
template<typename L, typename P>
L pixelToLevel(P p) {
return static_cast<L>(p);
}
template<>
uint8_t pixelToLevel<uint8_t, rgb8>(rgb8 p) { // <---------- line X
return pixelToLevel<uint8_t, uint8_t>(p.r());
}
int main()
{
pixelToLevel<uint8_t>(rgb8());
return 0;
}
但是如果我在第 X 行中将 rgb8 p
更改为 const rgb8& p
,它会编译失败。
(生成的确切编译器错误取决于显式模板参数 rgb8
是否也更改为 const rgb8&
。)
如果我想通过引用而不是 X 行中的值传递 p
,我该如何编译它?
您需要更改特化声明中的模板参数,以及调用它时的模板参数。否则将调用主模板。例如
template<>
uint8_t pixelToLevel<uint8_t, const rgb8&>(const rgb8& p) { // <---------- line X
return pixelToLevel<uint8_t, uint8_t>(p.r());
}
然后
pixelToLevel<uint8_t, const rgb8&>(rgb8());
编辑
给定 pixelToLevel<uint8_t>(rgb8());
,使用主模板执行模板参数推导,P
推导为 rgb8
(不会推导为当前主模板的 const rgb8&
模板的参数声明),则不会调用特化版本。
您可以应用重载而不是模板特化。例如
template<typename L, typename P>
L pixelToLevel(P p) {
return static_cast<L>(p);
}
template<typename L>
L pixelToLevel(const rgb8& p) { // <---------- line X
return pixelToLevel<L, uint8_t>(p.r());
}
然后 pixelToLevel<uint8_t>(rgb8());
会 select 第二次重载。
@songyuanyao 的另一种解决方案是
template<typename L, typename P>
L pixelToLevel(const P& p) {
return static_cast<L>(p);
}