以下代码是一个类似于元组的类的片段,可以在元组中获取对给定类型的引用,或者如果找不到该类型,则会返回提供的默认值。
如果默认值是左值,则必须返回引用,如果默认值是右值,则必须返回右值。
以下代码说明了我遇到的问题:
struct Foo {
Foo(int d) : data(d) {}
template <typename T, typename TT>
const TT get_or_default(TT&& t) const {
return data;
}
template <typename T, typename TT>
TT get_or_default(TT&& t) {
return data;
}
int data;
};
int main(int argc, char* argv[]) {
int i = 6;
const Foo foo1(5);
Foo foo2(5);
// compile error
foo1.get_or_default<int>(i);
// works
foo1.get_or_default<int>(5);
foo2.get_or_default<int>(i) = 4;
foo2.get_or_default<char>('a');
return 0;
}
编译时,我收到以下错误:
cxx.cxx:6:20: error: binding of reference to type 'int' to a value of type 'const int' drops qualifiers
return data;
^~~~
cxx.cxx:23:14: note: in instantiation of function template specialization 'Foo::get_or_default<int, int &>' requested here
foo1.get_or_default<int>(i);
^
1 error generated.
答案 0 :(得分:1)
当函数参数的类型为T&&
,其中T
是模板参数时,模板参数推导有一个特殊规则。该规则是:
如果函数参数是
U
类型的左值,则在这种情况下使用U&
代替U
进行类型推导。
它用于完美转发。基本上,这意味着模板参数T&&
的{{1}}是“通用参考”。
在您的情况下,由于T
确实是左值,i
被推断为TT
。将int&
应用于该值将被忽略(它将应用于引用本身,而不是引用的类型),因此从模板实例化的函数看起来像这样:
const
由于函数为int& get_or_default(int& t) const {
return data;
}
,const
也被视为data
,因此无法绑定到非const引用。