特质看看是否存在move构造函数

问题描述

如何询问编译器类型是否具有移动构造函数

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,则可以自己编写此特征,也可以在需要时使用右侧,因为它很短。