5

首先,我构造了四个结构,每个结构都返回值、左值引用、常量左值引用、右值引用。我在包装器(BC)中使用它们,在func()这些包装器的方法中,我想保留 of 的引用和 cvfunc()限定符 A

在 c++11 中,我使用了尾随返回类型。但是随着 c++14 中正常返回类型推导的到来,我猜我可以跳过尾随部分,但只有使用auto,返回类型会像普通一样忽略限定符和引用auto

然后,我的问题是在 c++14 中实现它的最佳方法是什么,它的行为就像B下面的类?有时写尾随部分(通常是 decltype(return expression))是微不足道的。

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");
}

请注意,此程序在带有 -std=c++1y 选项的 gcc 4.8 中编译没有问题。

4

1 回答 1

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 快照中实现了这一点,请参阅 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)

—结束示例]

于 2013-05-30T02:44:34.313 回答