Per*_*tte 4 c++ variadic-templates
在 C++ 中,我有一组可变参数模板函数,我希望接受任意数量的参数,可以是常量引用,也可以作为右值引用(这样我可以在可能的情况下移动内容而不是复制)。但是,我发现即使我将参数包装在std::move().
// Accept end of parameters.
void example () {}
// Accept a non-constant R-value reference to do a move
template <typename... More>
void example (std::string &&value, More... parameters) {
std::cout << value << ": moved" << std::endl;
example (parameters...);
}
// Accept a constant reference parameter.
template <typename... More>
void example (const std::string &value, More... parameters) {
std::cout << value << ": copied" << std::endl;
example (parameters...);
}
int main (int, char **) {
std::string first { "first" };
std::string second { "second" };
std::string third { "third" };
std::cout << "Trying variadic with move as second parameter: " << std::endl;
example (first, std::move (second), third);
// std::cout << "Trying variadic with move as first parameter: " << std::endl;
// This next line won't even compile when uncommented
// example (std::move (first), std::move (second), third);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Trying variadic with move as second parameter:
first: copied
second: copied
third: copied
Run Code Online (Sandbox Code Playgroud)
而不是预期的:
Trying variadic with move as second parameter:
first: copied
second: moved
third: copied
Run Code Online (Sandbox Code Playgroud)
作为奖励,当我将第一个参数包装在 中时std::move(),我在 g++7 和 clang 9 上都收到编译错误。
我究竟做错了什么?
这里有几个问题:
More... parameters始终按值接收参数(只要推导模板参数),因为typename ...More永远不会将类型推导为引用。
example传递给in 的所有参数example(parameters...);始终是左值。
重载string &&无法调用该重载const string &,因为此时尚未声明它。
您应该使用转发引用和 ,而不是按值传递std::forward。并且您需要const string &在定义重载之前声明重载string &&。
void example() {}
// Declare lvalue overload.
template <typename ...More>
void example(const std::string &value, More &&... parameters);
// Rvalue overload.
template <typename... More>
void example (std::string &&value, More &&... parameters) {
std::cout << value << ": moved" << std::endl;
example(std::forward<More>(parameters)...);
}
// Lvalue overload.
template <typename ...More>
void example(const std::string &value, More &&... parameters) {
std::cout << value << ": copied" << std::endl;
example(std::forward<More>(parameters)...);
}
Run Code Online (Sandbox Code Playgroud)