C++11 C++;11右值参考和常数

C++11 C++;11右值参考和常数,c++11,rvalue-reference,C++11,Rvalue Reference,下面的代码是一个类似元组的类的片段,在该类中可以获取对元组中给定类型的引用,或者如果找不到该类型,则将返回提供的默认值 如果默认值是左值,则必须返回引用;如果默认值是右值,则必须返回右值 以下代码说明了我遇到的问题: struct Foo { Foo(int d) : data(d) {} template <typename T, typename TT> const TT get_or_default(TT&& t) const {

下面的代码是一个类似元组的类的片段,在该类中可以获取对元组中给定类型的引用,或者如果找不到该类型,则将返回提供的默认值

如果默认值是左值,则必须返回引用;如果默认值是右值,则必须返回右值

以下代码说明了我遇到的问题:

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;
}
structfoo{
Foo(intd):数据(d){
模板
常量TT获取或默认值(TT&t)常量{
返回数据;
}
模板
TT获取或默认值(TT&t){
返回数据;
}
int数据;
};
int main(int argc,char*argv[]){
int i=6;
警察富福1(5);
富富2(5),;
//编译错误
foo1.get_或_default(i);
//工作
foo1.get_或_default(5);
foo2.get_或_default(i)=4;
foo2.get_或_default('a');
返回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.
cxx.cxx:6:20:错误:将对类型“int”的引用绑定到类型“const int”的值会删除限定符
返回数据;
^~~~
cxx.cxx:23:14:注意:在函数模板专门化的实例化中,此处请求“Foo::get\u或\u default”
foo1.get_或_default(i);
^
生成1个错误。

当函数参数类型为
T&
时,模板参数推导有一个特殊规则,其中
T
是模板参数。这条规则是:

如果函数参数是
U
类型的左值,则在这种情况下,使用
U&
代替
U
进行类型推断

它用于允许完美的转发。基本上,这意味着模板参数
T
T&
是一个“通用参考”

在您的例子中,由于
i
确实是一个左值,
TT
被推断为
int&
。将
常量应用于被忽略的对象(它将应用于引用本身,而不是引用的类型),因此从模板实例化的函数如下所示:

int& get_or_default(int& t) const {
  return data;
}

由于函数是
常量
数据
也被视为
常量
,因此它不能绑定到非常量引用。

foo.get\u或\u default(i)未声明foo…这是一种类型,现已修复原型如下:
常量TT get\u或_default(TT&&t)const
您删除了返回类型的常量。@Allan I没有,答案解决了它。重新阅读:“
TT
被推断为
int&
。将
const
应用于被忽略的对象(它将应用于引用本身,而不是引用的类型)。”当您键入
const int&
时,它意味着键入
const TT
时“引用常量
int
”,当
TT
int&
时,它的意思是“常量
TT
”,即类似于“常量引用
int
”,这实际上与“引用
int
”相同。我明白你的意思了-很抱歉评论。但你能建议我如何解决这个问题吗?当提供左值时,它返回的引用很重要。我找到了一个解决方案,其中包括编写自己的add_cost helper类并使用它来更改返回类型,但我不确定这是否是正确的方法(std::add_const不会将const添加到引用中)@Allan我相信一个定制的类型特征可以保持
int
一个
int
,但是将
int&
转换为
const int&
是一个不错的选择-标准库中没有任何东西可以为您做到这一点。