Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 转发引用始终被视为右值引用_C++_C++11 - Fatal编程技术网

C++ 转发引用始终被视为右值引用

C++ 转发引用始终被视为右值引用,c++,c++11,C++,C++11,我有一段“复杂”的代码,看起来像这样: namespace details { template <typename T> T do_smth_impl (T&& v) { // process return std::move (v); } } template <typename T> T do_smth (T v) { return details::do_smth_impl (std::move (v)); } 名称

我有一段“复杂”的代码,看起来像这样:

namespace details {

template <typename T>
T do_smth_impl (T&& v) {
    // process
    return std::move (v);
}

}

template <typename T>
T do_smth (T v) {
    return details::do_smth_impl (std::move (v));
}
名称空间详细信息{
模板
T do_smth_impl(T&v){
//过程
返回std::move(v);
}
}
模板
T do_smth(T v){
返回详细信息::do_smth_impl(std::move(v));
}

details::do_smth_impl()
接受转发引用,但由于它位于
details
命名空间中,并且仅用作实现细节(在本例中,不需要将其放在不同的函数中,但我确实需要将其分开,因为有多个
do_impl())
处理不同类型的函数)并且我确信只有右值引用会传递给impl函数是否需要返回
std::forward(v)

只是
forward
。有一天,有人(可能是你!)会添加一个对
do\u smth\u impl()
的调用,并给它一个左值,然后该调用会编译,然后突然你的左值在你没有预料到的情况下被移动了。您将花一段时间对其进行调试,然后将其更改为
forward
。写“<代码> STD:”:“移动< /代码>超过<代码> STD::向前/<代码>(我不认为低字符计数有好处)。 如果您真的打算在这个函数上只接受右值,那么您应该在它的接口中显式地使用它。SFINAE:

template <typename T, std::enable_if_t<!std::is_reference<T>::value, int> = 0>
void do_smth_impl(T&&);
这将使您的假设调用的左值无法编译。不编译是比编译和做错事更好的选择。然后,也许,在那个调用站点,你可以花时间认真考虑是否把LValk传递给这个函数是你想做还是不想做。也许传递左值是一个错误,现在你抓住了它


但是让函数保持原样,从转发引用中执行
移动
,只是自找麻烦。

如果有很多地方需要这样的要求,您可以使用下一种技术:

template <typename T, typename = typename std::enable_if<std::is_rvalue_reference<T&&>::value>::type>
using require_rvalue = T&&;

template <typename T>
void do_smth_impl(require_rvalue<T> val) {
    ...
}
模板
使用require\u rvalue=T&;
模板
无效执行(要求正确值){
...
}

你想避免使用std::forward有什么特别的原因吗?@FrançoisAndrieux没有,只是问一下。那为什么还要麻烦转发参考呢?为什么不让
do\u smth\u impl
按值接收?出于好奇,模板中
=0
的目的是什么?我已经看过多次了,但我不确定为什么要使用它。@BradyDean我们有一个非类型模板参数,其类型在替换失败或
int
,因此它需要一个默认参数。我现在明白了,这也是
..>*=nullptr
常见的原因吗?将指针设置为null对于所有类型都是通用的。@BradyDean Yep,同样的事情-除了更值得怀疑的是
void*
是否是有效的模板非类型参数,但是
int
没有任何问题。。。那么为什么不直接使用
int
template <typename T, typename = typename std::enable_if<std::is_rvalue_reference<T&&>::value>::type>
using require_rvalue = T&&;

template <typename T>
void do_smth_impl(require_rvalue<T> val) {
    ...
}