我正在玩这个小片段:
#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中通用完美转发为元组的正确方法的示例?
答案 0 :(得分:1)
auto t = std::make_tuple(std::forward<Ts>(xs)...);
这确实是将参数转换为元组的正确方法。
您获得的编译错误是由于明确声明copy_only
的移动构造函数已删除而引起的。通常,如果您声明了一个复制构造函数,它将被省略,并且在移动上下文中将选择复制构造函数 - 就像从C ++ 98开始一样。但是因为你明确地声明了它,它确实参与了重载决策并导致代码在被选中时格式不正确。
这可以通过从类定义中删除违规行来解决:
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
不是可构造的,因此不应声明它,也不应参与重载解析。