c++ - 当我知道传入的类型时,完美转发的最佳方式是什么

标签 c++ c++11

如果我理解正确的话,完美转发使用通用引用来推断传递的参数是左值还是右值。这很好。

也就是说,要实现这个功能,我必须制作模板函数。 一个可能的例子是

template <class T>
void func(T&& str){
    auto s = std::forward<T>(str);
    cout << s << endl;
}

但是,如果我知道 T 怎么办?的 func应该是 std::string仅有的?我认为一种可能的选择是使用 std::enable_ifstd::is_same限制类型 T .但它变得越来越冗长。

这种情况的最佳做法是什么?

编辑:

根据 Kerrek SB 的建议,我正在尝试制作一个可能的场景。

我正在制作一个包含 std::vector<double> 的类(class)作为成员(member)。 然后,我想制作一个也采用 std::vector<double> 的构造函数. 如果参数是左值,我想将它复制到一个成员,但如果不是,我想移动它。

这是某种可能的例子吗?

最佳答案

如果您不想要模板,您有两个选择:

  1. 按值传递并移动;
  2. 有一个拷贝重载和一个移动重载;

第一个选项将让编译器根据需要决定是移动还是复制到您的参数中。然后你的代码不再关心它是来自左值还是右值(如果它来自左值它已经是一个拷贝)并将其移动到成员中。撇开优化不谈,这可能会产生一次移动的开销,但如果移动成本较低(如 std::vector 的情况),则可以忽略不计。

foo(std::vector<double> v) : v(std::move(v)) {}

对于第二个选项,您的代码而不是编译器做出决定。这避免了前面提到的一次移动可能产生的开销,但它存在不可扩展的问题:如果你想复制或移动四个这样的参数,你将需要十六个不同的重载(这正是完美转发试图解决的问题).

foo(std::vector<double> const& v) : v(v) {}
foo(std::vector<double>&& v) : v(std::move(v)) {}

模板选项将适当缩放,但可能需要一些约束以防止在不希望的情况下使用它(在不受约束的模板构造函数的情况下,它可以是 mistakenly used for copies )。

当然,如果您使用移动退化为拷贝的类型(如 std::array),您可以只使用该集合的第一个重载。

关于c++ - 当我知道传入的类型时,完美转发的最佳方式是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17209650/

相关文章:

c++ - 为什么我不能将 const 左值引用绑定(bind)到返回 T&& 的函数?

c++ - 用 c++0x 和 MingW 编译 CImg

c++ - 在 lambda 闭包中复制的 const 对象不可变

c++ - 使 boost::fast_pool_allocator 与可变参数模板一起工作 (emplace)

c++ - 需要帮助为 JNI 调用构建 DLL。 Unresolved external 引用。 Borland 编译器

C++ 重载转换运算符

c++ - 函数原型(prototype)由于重载而干扰按引用传递?

c++ - 为什么这个指针/整数比较会产生段错误?

c++ - 如何获取当前持有的变体类型,并定义该类型的新变量

c++ - 使用参数初始化局部静态