可变参数模板函数右值参数默默地将 C++ 移动到函数中
Variadic template function rvalue parameters silently moved C++ to the function
以下代码编译并打印:move move
。我宁愿它没有编译,因为 merge
接受右值引用并且我不将 t1
和 t2
移动到它。
class A {
public:
A() = default;
A(const A& other) { std::cout << "copy "; };
A(A&& other) { std::cout << "move "; };
};
template <typename... TupleType>
auto merge(TupleType&&... tuples) {
return std::tuple_cat(std::move(tuples)...);
}
int main() {
std::tuple<int> t1{1};
std::tuple<A> t2{A()};
auto t3 = merge(t1, t2);
}
我不确定这里发生了什么以及为什么。此外,我认为这种行为是危险的:我在对 merge
的调用中没有移动,但是 t1
和 t2
被移动了。
为什么允许这样做,我怎样才能使 merge
只接受右值引用?
为什么这是可能的,请参阅 Reference_collapsing。
现在如果你想阻止你的函数接受lvalue
s,你可以使用下面的代码
#include <tuple>
#include <iostream>
class A {
public:
A() = default;
A(const A& other) { std::cout << "\ncopy "; }
A(A&& other)noexcept { std::cout << "\nmove "; }
};
template <typename... TupleType>
auto merge(TupleType&... tuples) = delete;
template <typename... TupleType>
auto merge(TupleType&&... tuples) {
return std::tuple_cat(std::forward<TupleType>(tuples)...);
}
int main() {
std::tuple<int> t1{1};
std::tuple<A> t2{A()};
// auto t3 = merge(t1, t2);//won't compile
//compiles and gives the desired behavior move move
auto t4 = merge(std::make_tuple(1), std::make_tuple(A{}));
}
以下代码编译并打印:move move
。我宁愿它没有编译,因为 merge
接受右值引用并且我不将 t1
和 t2
移动到它。
class A {
public:
A() = default;
A(const A& other) { std::cout << "copy "; };
A(A&& other) { std::cout << "move "; };
};
template <typename... TupleType>
auto merge(TupleType&&... tuples) {
return std::tuple_cat(std::move(tuples)...);
}
int main() {
std::tuple<int> t1{1};
std::tuple<A> t2{A()};
auto t3 = merge(t1, t2);
}
我不确定这里发生了什么以及为什么。此外,我认为这种行为是危险的:我在对 merge
的调用中没有移动,但是 t1
和 t2
被移动了。
为什么允许这样做,我怎样才能使 merge
只接受右值引用?
为什么这是可能的,请参阅 Reference_collapsing。
现在如果你想阻止你的函数接受lvalue
s,你可以使用下面的代码
#include <tuple>
#include <iostream>
class A {
public:
A() = default;
A(const A& other) { std::cout << "\ncopy "; }
A(A&& other)noexcept { std::cout << "\nmove "; }
};
template <typename... TupleType>
auto merge(TupleType&... tuples) = delete;
template <typename... TupleType>
auto merge(TupleType&&... tuples) {
return std::tuple_cat(std::forward<TupleType>(tuples)...);
}
int main() {
std::tuple<int> t1{1};
std::tuple<A> t2{A()};
// auto t3 = merge(t1, t2);//won't compile
//compiles and gives the desired behavior move move
auto t4 = merge(std::make_tuple(1), std::make_tuple(A{}));
}