【发布时间】:2014-09-03 17:34:42
【问题描述】:
如何强制模板类中的函数使用 auto/decltype 返回对成员变量的引用?
这是我正在尝试做的一个简单的例子。假设你有一个模板类,它在私有成员变量a_ 中存储一些东西,如下所示:
#include <iostream>
template <typename T>
class A
{
private:
T a_;
public:
A(T a) : a_(a) {}
// 1. Return const reference to a_
const T & get() const { return a_; }
// 2. Return non-const reference to a_
T & get() { return a_; }
};
int main(int argc, char *argv[])
{
A<int> a(3);
const auto & a1 = a.get(); // 1. Return const reference to a_
//a1 = 4; // Shouldn't compile
std::cout << "Value of a = " << a.get() << std::endl;
auto & a2 = a.get(); // 2. Return non-const reference to a_
a2 = 5;
std::cout << "Value of a = " << a.get() << std::endl;
return 0;
}
预期/期望的输出是:
Value of a = 3
Value of a = 5
但是现在,假设我希望编译器推断出 A<T> 中的 const 和非 const get() 函数返回的类型,并且我想确保两个调用都返回 references 到 @987654326 @。
我目前的最佳猜测是:
template <typename T>
class A
{
private:
T a_;
public:
A(T a) : a_(a) {}
// 1. Return const reference to a_
const auto get() const -> std::add_lvalue_reference<const decltype(a_)>::type
{
return a_;
}
// 2. Return non-const reference to a_
auto get() -> std::add_lvalue_reference<decltype(a_)>::type
{
return a_;
}
};
但是编译失败。 GCC给出的第一个错误是:
decltype.cpp:11:29: error: expected type-specifier
decltype.cpp:11:26: error: expected ‘;’ at end of member declaration
decltype.cpp:11:29: error: ‘add_lvalue_reference’ in namespace ‘std’ does not name a type
这样做的动机不在于我提炼的示例代码,而是源于试图减少模板采用的参数数量,当这些参数中的一个(或多个)仅用于指定编译器应该的返回类型时(我认为)能够自行推断。注意:在现实世界中,get() 的返回类型不是a_ 的返回类型,而是某个函数f(a_) 的返回类型,我知道它可以被编译器推导出来。因此在这个例子中我需要 auto/decltype。
让我感到困惑的是,编译器可以在非模板类中使用几乎相同的代码正确推断返回类型:
class A
{
private:
int a_;
public:
A(int a) : a_(a) {}
// 1. Return const reference to a_
const auto get() const -> std::add_lvalue_reference<const decltype(a_)>::type
{
return a_;
}
// 2. Return non-const reference to a_
auto get() -> std::add_lvalue_reference<decltype(a_)>::type
{
return a_;
}
};
任何帮助理解我所缺少的东西将不胜感激。
详情:
Centos 6.5
gcc (GCC) 4.7.2 20121015 (Red Hat 4.7.2-5)
【问题讨论】:
-
const auto get() const对于尾随返回类型,您只能在函数名称前使用auto,而不是const auto。 -
@Praetorian 我认为该段落并没有直接禁止使用
const auto,因为它也适用于变量声明(auto被替换)。但是,请查看 [dcl.fct]/2 明确禁止它 -
@jrok 8.3.5[dcl.fct]/p2 说“在声明
T D中,D的形式为 [带有尾随返回类型的函数声明语法],T应成为单个类型说明符auto。" -
@Praetorian Well [dcl.spec.auto] 确实隐式允许 cv-qualifications; [dcl.fct]/2 需要使用trailing-return-type,不能与
decltype(auto)结合使用。 -
作为对任何访问者的澄清,
const auto在这种情况下无论如何都不需要;与使用auto的变量声明不同,函数自动 确实 维护 cv-qualification。
标签: c++ templates c++11 auto decltype