How can I check if a move constructor is being generated implicitly?

前端 未结 3 2040
一向
一向 2021-02-04 04:20

I have several classes for which I wish to check whether a default move constructor is being generated. Is there a way to check this (be it a compile-time assertion, or parsing

相关标签:
3条回答
  • 2021-02-04 04:53
    1. disable inlining (-fno-inline)
    2. either
      • make sure a move constructor can be used by the code, or (better)
      • temporarily add a call to std::move(MyStruct) anywhere in the compiled code to meet the odr-used requirement
    3. either
      • make sure that MyStruct has at least one parent class or a non-static member (recursively), with a non-trivial move constructor (e.g. an std::string would suffice), or (easier)
      • temporarily add an std::string member to your class
    4. compile/link and run the resultant object file through nm -C ... | grep 'MyStruct.*&&'

    The result will imply whether the move constructor was generated or not.


    As discussed in the question itself, this method didn't seem to work reliably, but after fixing the two issues that made it unreliable: inlining and triviality of the move constructor, it turned out to be a working method.

    Whether the generated move constructor is implicitly or explicitly defaulted plays no role—whether the default is trivial or not is relevant: a trivial move (and copy) constructor will simply perform a byte-wise copy of the object.

    0 讨论(0)
  • 2021-02-04 04:58

    Declare the special member functions you want to exist in MyStruct, but don't default the ones you want to check. Suppose you care about the move functions and also want to make sure that the move constructor is noexcept:

    struct MyStruct {
        MyStruct() = default;
        MyStruct(const MyStruct&) = default;
        MyStruct(MyStruct&&) noexcept; // no = default; here
        MyStruct& operator=(const MyStruct&) = default;
        MyStruct& operator=(MyStruct&&); // or here
    };
    

    Then explicitly default them, outside the class definition:

    inline MyStruct::MyStruct(MyStruct&&) noexcept = default;
    inline MyStruct& MyStruct::operator=(MyStruct&&) = default;
    

    This triggers a compile-time error if the defaulted function would be implicitly defined as deleted.

    0 讨论(0)
  • 2021-02-04 05:02

    As Yakk pointed out, it's often not relevant if it's compiler generated or not.

    You can check if a type is trivial or nothrow move constructable

    template< class T >
    struct is_trivially_move_constructible;
    
    template< class T >
    struct is_nothrow_move_constructible;
    

    http://en.cppreference.com/w/cpp/types/is_move_constructible

    Limitation; it also permits trivial/nothrow copy construction.

    0 讨论(0)
提交回复
热议问题