【问题标题】:Trait to see if a move constructor exists判断是否存在移动构造函数的特征
【发布时间】: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


【解决方案1】:

您似乎正在寻找的概念是:

template <typename T>
concept C = not std::is_trivially_move_constructible_v<T>;

这是demo

如果你没有 c++20,你可以自己编写这个特性,或者在需要的地方使用右侧,因为它很短。

【讨论】:

  • 您回答了您将我的问题编辑为的内容,但这对原始问题没有帮助......这是一个示例:godbolt.org/z/TPe66q
猜你喜欢
  • 1970-01-01
  • 2014-11-08
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
相关资源
最近更新 更多