Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++ 我的通用模板应该使用T还是T&&;?_C++_Templates_C++11 - Fatal编程技术网

C++ 我的通用模板应该使用T还是T&&;?

C++ 我的通用模板应该使用T还是T&&;?,c++,templates,c++11,C++,Templates,C++11,我在一个文件中工作,该文件有一个给定的函数和许多重载,如下所示: inline X f(ScriptWrappable* impl, Y y, Z z) { ... } inline X f(Node* impl, Y y, Z z) { ... } inline X f(RawPtr<T> impl, Y y, Z z) { ... } inline X f(const RefPtr<T>& impl, Y y, Z z) { ... } inline X f(

我在一个文件中工作,该文件有一个给定的函数和许多重载,如下所示:

inline X f(ScriptWrappable* impl, Y y, Z z) { ... }
inline X f(Node* impl, Y y, Z z) { ... }
inline X f(RawPtr<T> impl, Y y, Z z) { ... }
inline X f(const RefPtr<T>& impl, Y y, Z z) { ... }
inline X f(ScriptWrappable* impl, Y y, Z z) { ... }
inline X f(const String& impl, Y y, Z z) { ... }
inline X f(int64_t impl, Y y, Z z) { ... }
template<typename T, size_t capacity> inline X f(const Vector<T, capacity>& impl, Y y, Z z) { ... }
template<typename T> inline X f(T impl, W w) {
  return f(impl, w->getY(), w->getZ());
}
我真的不知道这个问题的答案。我以为我了解通用参考文献,但我不知道它们是好主意还是坏主意。在我选择其中一个的情况下会有什么后果


如果我不得不猜测的话,我会说,由于T可以代表的原始类型都是易于复制的(原语、引用或指针),T&&不会带来太多好处。但是我仍然很好奇,例如,是否有任何类型可以传递到T&&version,而不能传递到T版本,或者反之亦然。

您应该这样编写函数:

template<typename T> inline X f(T&& impl, W w) {
  return f(std::forward<T>(impl), w->getY(), w->getZ());
}
模板内联X f(T&&impl,W){
返回f(std::forward(impl),w->getY(),w->getZ());
}

这就是所谓的完美转发。
impl
的类型将与您直接调用
f
的类型完全相同。它不一定是r值引用。

答案有点复杂,因为它需要对编译器关于模板的规则有一些了解

在以下声明中:

template<class T> void func(T&& t);
在这种情况下,foo实际上需要一个r值引用

这也不是推论的背景:

template<class T>
struct X {
  void foo(T&& t);
};
template<class T>
void foo(std::vector<T>&& v);
模板
void foo(std::vector&&v);

在这两种情况下,您应该使用
std::move

如果调用方想要移动,他应该只
std::move
参数。使用
T&
你是在强迫他这么做。只使用
T
你给了他一个选择。在推断上下文中使用模板时,这是不正确的。我不知道这一点。谢谢你的澄清。const参考似乎足够了。谢谢!听起来完美的转发更符合我的意图。我仍然希望了解如果我选择了其他替代方案,会发生什么不同,但搜索“完美转发”会给我类似的页面似乎有所帮助。看看Richard Hodges的答案。@TobiasBrandt,除非f打算拥有impl,否则为什么不使用const T&。@JohanLundberg
T&
更一般。例如,如果
T=int
并且存在过载
f(int,Y,Z)
,则将拾取该过载。如果只有
f(const int&,Y,Z)
的重载,则将选择该重载。这将选择是使用“按值传递”还是“按常量引用传递”移动到它所属的(非模板)
f
的实现中。@TobiasBrandt,“这将选择…移动到它所属的…f”。这一点很清楚,我也同意。不是在推导的上下文中对
t
的评估使其成为r值或l值参考<代码>类型定义int&T;typedef T&X没有推导出的上下文,但是
X
的类型是
int&
。替换为
typedef int T
X
成为
int&
类型。在进行右值或左值引用时,不存在涉及演绎的魔法;这就是引用折叠规则。演绎规则确实会导致
T&&
中的
T
以某种方式被演绎,以允许所述规则生成l或r值引用,但这是一个真正的区别。如果我的措辞有误,请原谅。单词的正确形式是什么?那些可以的,发布。不能批评别人的人,批评别人的帖子。:)从函数参数和转发引用中谈论模板类型推断所需的词语选择很困难。
template<class T>
void foo(std::vector<T>&& v);