删除decltype中的引用(返回T而不是T&,其中T&是decltype)

lee*_*mes 46 c++ templates c++11 type-deduction

(如果您是C++ 11专业版,请跳到粗体段.)

假设我想编写一个模板方法,该方法调用并返回传递对象的结果,该对象的类型是模板参数:

template<ReturnType, T>
ReturnType doSomething(const T & foo) {
    return foo.bar(); // EDIT: Might also be an expression introducing a temp val
}
Run Code Online (Sandbox Code Playgroud)

所以T必须有一个方法ReturnType T::bar() const才能在这样的调用中使用:

struct MyClass {
    ...
    int bar() const;
    ...
};
...
MyClass object;
int x = doSomething<int, MyClass>(object);
Run Code Online (Sandbox Code Playgroud)

MyClass感谢类型扣除,我们无需写信,调用成为:

int x = doSomething<int>(object);
Run Code Online (Sandbox Code Playgroud)

但是省略<int>也会导致编译错误,因为该方法不需要返回int以便x以后分配(char例如,它可以返回).

在C++ 0X/11,我们有autodecltype,使我们可以用它来推断模板方法的返回类型:

template<T>
auto doSomething(const T & foo) -> decltype(foo.bar()) {
    return foo.bar(); // EDIT: Might also be an expression introducing a temp val
}
Run Code Online (Sandbox Code Playgroud)

编译器现在将找出它的类型,foo.bar()并将其用作返回类型.通过我们的具体课程,MyClass这将是一个int以下就足够了:

int x = doSomething(object);
Run Code Online (Sandbox Code Playgroud)

现在问我的问题:

如果MyClass定义bar()为返回an int&,则返回类型也doSomething(object)将为int&= decltype(foo.bar()).这是一个问题,因为G ++现在符合我正在返回临时引用.

我怎样才能解决这个问题?是否remove_reference可以使用类似的东西remove_reference(decltype(foo.bar()))

我想到了刚刚宣布一个辅助方法,这需要T&和返回T,然后定义的返回类型doSomethingdecltype(helper(foo.bar())).但是必须有更好的方法,我感觉到了.

GMa*_*ckG 52

删除引用:

#include <type_traits>

static_assert(std::is_same<int, std::remove_reference<int&>::type>::value, "wat");
Run Code Online (Sandbox Code Playgroud)

在你的情况下:

template <typename T>
auto doSomething(const T& foo)
    -> typename std::remove_reference<decltype(foo.bar())>::type
{
    return foo.bar();
}
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,请注意,在写入返回时,引用就可以了:

#include <type_traits>

struct f
{
    int& bar() const
    {
        static int i = 0;
        return i;
    } 
};

template <typename T>
auto doSomething(const T& foo)
    -> decltype(foo.bar())
{ 
    return foo.bar();
}

int main()
{
    f x;
    return doSomething(x);
}
Run Code Online (Sandbox Code Playgroud)

返回的引用可以简单地传递而不会出错.您在评论中的示例是它变得重要和有用的地方:

template <typename T>
auto doSomething(const T& foo)
    -> decltype(foo.bar())
{ 
    return foo.bar() + 1; // oops
}
Run Code Online (Sandbox Code Playgroud)

  • 在C++ 14中,您还可以使用`std :: remove_reference_t <int&>`. (5认同)
  • @Kupiakos在C++ 14中,您可以使用不带尾随decltype的自动返回类型. (3认同)