删除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中,我们可以使用auto和decltype来推断模板方法的返回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 }