C ++完美的前向只复制类型到make_tuple

时间:2016-11-10 20:01:41

标签: c++ perfect-forwarding stdtuple

我正在玩这个小片段:

#include <tuple>

struct copy_only
{
    copy_only() = default;
    copy_only(copy_only&&) = delete;
    copy_only(const copy_only&) = default;
};

template <typename ...Ts>
void foo(Ts&& ...xs)
{
    auto t = std::make_tuple(std::forward<Ts>(xs)...);
    (void) t;
}

int main()
{
   foo(copy_only{});
}

使用gcc7和clang3.6,clang3.7,clang3.8(Wandbox)和clang8.0(macOS Sierra)进行编译。它不用clang3.9,g ++ 6.2(macOS Sierra)和clang4.0(Wandbox)编译。所有人都抱怨删除了移动构造函数。

它适用于仅移动类型。至少在Wandbox上提供的上述编译器中。

此代码是否是在c ++ 14中通用完美转发为元组的正确方法的示例?

1 个答案:

答案 0 :(得分:1)

    auto t = std::make_tuple(std::forward<Ts>(xs)...);

这确实是将参数转换为元组的正确方法。

您获得的编译错误是由于明确声明copy_only的移动构造函数已删除而引起的。通常,如果您声明了一个复制构造函数,它将被省略,并且在移动上下文中将选择复制构造函数 - 就像从C ++ 98开始一样。但是因为你明确地声明了它,它确实参与了重载决策并导致代码在被选中时格式不正确。

这是一张有用的图表,由Howard Hinannt提供: chart

这可以通过从类定义中删除违规行来解决:

struct copy_only
{
    copy_only() = default;
    //copy_only(copy_only&&) = delete;
    copy_only(const copy_only&) = default;
};

现在,关于你的代码是否应该编译:据我所知,它应该。 tuple的移动构造函数定义为:

  

tuple(tuple&& u) = default;

     

需要is_move_constructible<Ti>::value适用于所有 i

由于copy_only不是可构造的,因此不应声明它,也不应参与重载解析。