【发布时间】:2020-08-23 11:36:59
【问题描述】:
如何询问编译器一个类型是否有移动构造函数?
std::is_move_constructible 不适用,因为它会返回 true,即使该类型仅可复制构造。
无论是否实际存在用户定义的移动构造函数,是否都会返回一些东西?
编辑:
作为背景,我正在尝试创建一个类型擦除的类,它将(给定一组类型)决定是否值得保存移动构造函数的类型擦除版本。
如果这些类型中的至少一种确实有一个“有趣”的移动构造函数(非平凡的并且实际实现),那么它应该节省移动构造函数,否则它不会并且会节省空间
#include <type_traits>
struct NoMove {
NoMove(NoMove const&) {}
//NoMove(NoMove&&) = delete;
};
struct InterestingMove {
InterestingMove(InterestingMove&&) {}
};
template<typename T>
struct is_interesting_move_constructor :
std::integral_constant<bool,
std::is_move_constructible<T>::value &&
!std::is_trivially_move_constructible<T>::value> {};
// Fails:
//static_assert(!is_interesting_move_constructor<NoMove>::value);
// Is fine:
static_assert(is_interesting_move_constructor<InterestingMove>::value);
这个尝试的问题是它应该在NoMove 上返回false,但它不会因为is_move_constructible 不会根据实际是否存在移动构造函数返回true
键入擦除的类草图(像std::any 一样思考,但仅限于一组类型):
template<typename... Ts> // One of these types will be held
struct type_eraser_thing
{
void* obj; // pointer to actual thing
std::function<void*(void*,void*)> move_constr;
std::function<void*(void*,void const*)> copy_constr;
// Plus other goodies not shown
std::size_t size;
template<typename T>
type_eraser_thing(T const& other)
{
// static_assert to make sure T is in Ts...
// Get the memory
obj = malloc(sizeof(T));
obj = new (obj) T(other);
size = sizeof(T);
// Save the move_constructor
move_constr = [](void* dest, void* src){
return new (dest) T(std::move(*reinterpret_cast<T*>(src)));
};
}
// Other stuff (copy constructor, etc)
//
// The real problem the move constructor:
type_eraser_thing(T&& other)
{
obj = malloc(other.size);
obj = other.move_constr(obj,other.obj);
obj.move_constr = other.move_constr;
other.obj = nullptr;
}
};
在移动构造函数的实现中,如果移动构造函数不做任何事情,那么调用 std::function(不是真的,但类似的东西)是没有意义的,所以我想 SFINAE 它如果它什么都不做就退出
【问题讨论】:
-
在什么情况下你会关心类型是移动还是复制?对于许多类型 - 例如
int- 两者无法区分。这个练习的最终目标是什么? -
@Igor 我正在创建一个类型擦除实用程序......我想要做的是如果类型集合中的至少一个类型具有“有趣”的移动构造函数,那么我将将类型擦除的 lambda 存储到该移动构造函数,以便我可以实现这种更大类型的擦除类型的移动赋值运算符
-
@Igor 但是如果这个集合都没有“有趣”的移动构造函数,那么存储它就没有意义
-
所以你想检查类型是否为只移动?
-
@cigien No....我想看看它是否有一个“有趣”的移动构造函数
标签: c++ templates template-meta-programming