右值参考或转发参考?

Mar*_*hrs 4 c++

我知道以下功能

template <typename T>
void do_something(T&& arg);
Run Code Online (Sandbox Code Playgroud)

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

template <typename T>
class MyClass
{
    void do_something(T&& arg);
};
Run Code Online (Sandbox Code Playgroud)

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

Sto*_*ica 7

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

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

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

template <typename T> void func(typename identity<T>::type&&);
Run Code Online (Sandbox Code Playgroud)

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

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

template<typename T>
void func(T&& s)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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


Sim*_*ple 5

此外,我想知道,如何强制执行右值引用

如果你总是想要一个推导上下文中的右值引用(而不是转发引用),那么你可以使用这个:

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)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

foo只能用右值被调用,并且T不会是一个参考值(即如果你打电话foostd::string&&,然后Tstd::string)。