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

(如果您是C ++ 11专业版,请跳至粗体段落。)

比方说,我想写一个模板方法,它调用并返回types是模板参数的传递对象的结果:

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

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

 struct MyClass { ... int bar() const; ... }; ... MyClass object; int x = doSomething<int, MyClass>(object); 

我们不必写MyClass感谢types扣除和调用变成:

 int x = doSomething<int>(object); 

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

在C ++ 0x / 11中,我们可以使用autodecltype来推断模板方法的返回types:

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

编译器现在将找出foo.bar()的types, foo.bar()其用作返回types。 用我们的具体类MyClass这将是一个int ,下面就足够了:

 int x = doSomething(object); 

现在我的问题:

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

我怎样才能解决这个问题? 有没有像remove_reference可以像remove_reference(decltype(foo.bar()))

我想只是声明一个帮助器方法,它接受一个T&并返回一个T ,然后定义doSomething的返回types为decltype(helper(foo.bar())) 。 但是有一个更好的方法,我感觉到了。

要删除参考:

 #include <type_traits> static_assert(std::is_same<int, std::remove_reference<int&>::type>::value, "wat"); 

在你的情况下:

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

要清楚,请注意,作为书面返回一个引用就好了:

 #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() { fx; return doSomething(x); } 

返回的引用可以简单地传递,没有错误。 你在评论中的例子是它变得重要和有用的地方:

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