右值参考或转发参考?

时间:2017-09-14 08:08:15

标签: c++

我知道以下功能

template <typename T>
void do_something(T&& arg);

function参数是转发引用。但在以下情况下,它仍然是转发引用或右值引用吗?

template <typename T>
class MyClass
{
    void do_something(T&& arg);
};

我认为它仍然是转发参考,但我不确定。此外,我想知道,如果结果不是我想要的,可以采取什么措施来强制执行右值引用或转发引用。

2 个答案:

答案 0 :(得分:6)

这是一个右值参考。转发引用只能出现在推断的上下文中。这只是一个成员函数,它接受对模板参数的右值引用。

如果要维护函数的模板参数推导,则不能强制转发引用为右值引用。如果你不介意在整个地方指定模板参数,那么这将始终只给出一个右值引用:

template<typename T> struct identity { using type = T; };

template <typename T> void func(typename identity<T>::type&&);

回想起来,实际上有一种方法可以保持演绎,但强制只接受右值引用(除了Simple的答案中的自我记录)。您可以提供已删除的左值超载:

template<typename T>
void func(T&) = delete;

template<typename T>
void func(T&& s)
{
    // ...
}

传递左值时,左值超载更加专业化。并且由于被删除,将给出一些有些明确的错误消息。

答案 1 :(得分:3)

  

此外,我想知道如何强制执行右值参考

如果您总是希望在推导的上下文中使用右值引用(而不是转发引用),那么您可以使用:

template<
    typename T,
    typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>
>
using rval_ref = T&&;

template<typename T>
void foo(rval_ref<T> s)
{
    // ...
}

foo只能使用右值调用,而T不会作为参考(即如果您使用foo致电std::string&&,则T将是std::string)。