0

以下代码编译并打印:move move. 我宁愿它没有编译,因为它需要右值引用并且merge我不会移动它。t1t2

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但被移动了。t1t2

为什么这是允许的,我怎样才能merge只使用右值引用?

4

1 回答 1

3

有关为什么这可能,请参阅Reference_collapses

现在如果你想阻止你的函数接受lvalues,你可以使用下面的代码

#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{}));
}

居住

于 2020-07-23T21:09:19.727 回答