删除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 }