C++ 完美转发仅复制类型到 make_tuple
C++ perfect forward copy-only types to make_tuple
我正在玩这个小片段:
#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 中将通用完美转发到元组的正确方法的示例吗?
auto t = std::make_tuple(std::forward<Ts>(xs)...);
这确实是将参数转发到元组中的正确方法。
您得到的编译错误是由于显式声明 copy_only
的移动构造函数已删除引起的。通常,如果您声明了一个复制构造函数,它会被省略,并且在移动上下文中会选择复制构造函数——自 C++98 以来一直如此。但是因为您显式声明了它,所以它确实参与了重载决议并导致代码在选择时格式错误。
这是 Howard Hinannt 提供的有用图表:
这可以通过从 class 定义中删除有问题的行来解决:
struct copy_only
{
copy_only() = default;
//copy_only(copy_only&&) = delete;
copy_only(const copy_only&) = default;
};
现在,关于您的代码是否应该编译:据我所知,应该。 tuple
的移动构造函数定义为:
tuple(tuple&& u) = default;
Requires: is_move_constructible<Ti>::value
is true for all i.
由于 copy_only
不可移动构造,因此不应声明也不应参与重载决策。
我正在玩这个小片段:
#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 中将通用完美转发到元组的正确方法的示例吗?
auto t = std::make_tuple(std::forward<Ts>(xs)...);
这确实是将参数转发到元组中的正确方法。
您得到的编译错误是由于显式声明 copy_only
的移动构造函数已删除引起的。通常,如果您声明了一个复制构造函数,它会被省略,并且在移动上下文中会选择复制构造函数——自 C++98 以来一直如此。但是因为您显式声明了它,所以它确实参与了重载决议并导致代码在选择时格式错误。
这是 Howard Hinannt 提供的有用图表:
这可以通过从 class 定义中删除有问题的行来解决:
struct copy_only
{
copy_only() = default;
//copy_only(copy_only&&) = delete;
copy_only(const copy_only&) = default;
};
现在,关于您的代码是否应该编译:据我所知,应该。 tuple
的移动构造函数定义为:
tuple(tuple&& u) = default;
Requires:
is_move_constructible<Ti>::value
is true for all i.
由于 copy_only
不可移动构造,因此不应声明也不应参与重载决策。