问题描述
如何询问编译器类型是否具有移动构造函数?
std::is_move_constructible
不适用,因为即使类型只能是可复制构造的,它也会返回true
。
是否存在一些将返回的值,而实际上是否存在用户定义的move构造函数?
编辑:
对于背景,我正在尝试创建一个类型擦除的类,该类将(给定一组类型)决定是否值得保存move构造函数的类型擦除的版本。
如果这些类型中的至少一种确实具有“有趣的” move构造函数(非琐碎且实际上没有实现),则它应避免使用move构造函数,否则将不会,并且将节省空间
#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);
此尝试的问题在于它应该在false
上返回NoMove
,但这并不是因为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;
}
};
在move构造函数的实现中,如果move构造函数没有执行任何操作,则没有必要调用std::function
(不是真的,但是类似),所以我想SFINAE找出它什么都不做
解决方法
您似乎要寻找的概念是:
template <typename T>
concept C = not std::is_trivially_move_constructible_v<T>;
这里是demo。
如果您没有c ++ 20,则可以自己编写此特征,也可以在需要时使用右侧,因为它很短。