Is there a way to test whether a C++ class has a default constructor (other than compiler-provided type traits)?

后端 未结 7 2137
花落未央
花落未央 2020-11-28 13:00

Traits classes can be defined to check if a C++ class has a member variable, function or a type (see here).

Curiously, the ConceptTraits do not include traits to che

7条回答
  •  独厮守ぢ
    2020-11-28 13:17

    Warning: some analysis below is obsolete as of C++11. In C++11, access checking is done prior to instantiation and access violation is-not-an-error. Therefore the attached code may be more compliant. I haven't re-analyzed it.


    I'm pretty new to SFINAE. Today it occurred to me to put a test expression inside a sizeof inside a template parameter in a function argument type.

    According to N2634 this is not wrong, but highly unportable. (EDIT: appears to be compliant to C++0x FCD.) It can only return positive or fail to compile in GCC 4.2; GCC 4.5 scores a 3 out of 3 for my test cases.

    The SFINAE rules were broadened (in this case) since C++03 in the FCD. New §14.8.2/8 (emphasis mine):

    If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. Access checking is not done as part of the substitution process. Consequently, when deduction succeeds, an access error could still result when the function is instantiated. Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [ Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the “immediate context” and can result in the program being ill-formed.

    template< class T >
    class is_default_constructible {
        template
        class receive_size{};
    
        template< class U >
        static int sfinae( receive_size< sizeof U() > * );
    
        template< class U >
        static char sfinae( ... );
    
    public:
        enum { value = sizeof( sfinae(0) ) == sizeof(int) };
    };
    
    class q { q(); };
    class r { r(int); };
    
    #include 
    using namespace std;
    
    int main() {
        cerr << is_default_constructible::value << endl // outputs 1
            // fails to compile: access violation
            // FCD demands that access violations be unrecoverable
            // indeed, it's murky: q is default-constructible, but only "rarely"
            //<< is_default_constructible::value << endl
            << is_default_constructible::value << endl; // outputs 0
    }
    

提交回复
热议问题