首先,我构造了四个结构,每个结构返回值,l值引用,const l值引用,r值引用。我在这些包装器的方法B
中的包装器(C
或func()
)中使用它们,
我想保留func()
A
的引用和cv限定符。
在c ++ 11中,我使用了尾随返回类型。但是随着c ++ 14中普通返回类型推导的到来,我猜测我可以跳过尾随部分,但只有auto
,返回类型忽略限定符和引用,就像普通的auto
一样。
然后,我的问题是在c ++ 14中实现它的最佳方法是什么,其行为与下面的B
类似?
当它很简单的时候写尾随部分(通常是decltype(返回表达式))有时很沮丧。
struct A1 {
int func(){
return x;
}
int x{3};
};
struct A2 {
int& func(){
return x;
}
int x{3};
};
struct A3 {
const int& func(){
return x;
}
int x{3};
};
struct A4 {
int&& func(){
return std::move(x);
}
int x{3};
};
template <class A>
struct B{
auto func() -> decltype(std::declval<A>().func())
{
return a.func();
}
A a;
};
template <class A>
struct C{
auto func()
{
return a.func();
}
A a;
};
int main(){
std::cout << std::boolalpha;
B<A1> b1;
B<A2> b2;
B<A3> b3;
B<A4> b4;
static_assert(std::is_same<decltype(b1.func()), int>::value, "true");
static_assert(std::is_same<decltype(b2.func()), int&>::value, "true");
static_assert(std::is_same<decltype(b3.func()), const int&>::value, "true");
static_assert(std::is_same<decltype(b4.func()), int&&>::value, "true");
C<A1> c1;
C<A2> c2;
C<A3> c3;
C<A4> c4;
static_assert(std::is_same<decltype(c1.func()), int>::value, "true");
static_assert(std::is_same<decltype(c2.func()), int>::value, "true");
static_assert(std::is_same<decltype(c3.func()), int>::value, "true");
static_assert(std::is_same<decltype(c4.func()), int>::value, "true");
}
请注意,此程序在gcc 4.8中使用-std = c ++ 1y选项编译时没有问题。
答案 0 :(得分:10)
C ++ 14的提案包括一个(N3638,由Jason Merrill提出),它使用decltype(auto)
代替auto
定义了一个特殊声明:
template <class A>
struct C{
decltype(auto) func()
{
return a.func();
}
A a;
};
GCC在4.9 snapshot中实现了这一点,请参阅C ++部分。
将代码的最后部分更改为
static_assert(std::is_same<decltype(c1.func()), int>::value, "true");
static_assert(std::is_same<decltype(c2.func()), int&>::value, "true");
static_assert(std::is_same<decltype(c3.func()), const int&>::value, "true");
static_assert(std::is_same<decltype(c4.func()), int&&>::value, "true");
GCC 4.9快照编译它,而4.8不编译它。
(注意:如果在编译时使用-g
选项,两个编译器都会因内部编译器错误而崩溃。这是由Bug 56014引起的。)
为了完整起见,以下是该提案中最相关的部分:
如果占位符是decltype(auto)类型说明符,则函数的声明类型或函数的返回类型应仅为占位符。根据7.1.6.2中的描述确定为变量或返回类型推导出的类型,就好像初始化器是decltype的操作数一样。 [例如:
int i; int&& f(); auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)
- 结束示例]