Conditional compilation of templates

前端 未结 2 1585
天命终不由人
天命终不由人 2020-12-22 05:00

I am trying to get static_assert to help me avoid null pointers in C++11.

The problem seems to be that C++11 require the compiler to compile templates even if they a

相关标签:
2条回答
  • 2020-12-22 05:22

    In all C++ standards ever, templates are compiled in two phases. The second phase is instantiation, but compilation can also fail in phase 1. In particular, syntax errors are detected in phase 1.

    In your case, the simpler solution is to leave out the body of the second instantiation.

    Another solution is to use T in the static_assert, so the compiler must delay evaluation to phase 2. Trivially: static_assert(sizeof(T)==0,

    0 讨论(0)
  • 2020-12-22 05:44

    The standard permits, but does not require, compilers to diagnose templates for which no valid instantiation can be generated. This can range from simple syntax errors to your example of a constant false expression in a static_assert. §14.6 [temp.res]/p8:

    If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

    I'm rather baffled by all this SFINAE machinery, though. A simple

    template<typename T, typename... Us>
    T* create_if_constructible(Us... args) { return new T(args...); }
    

    already refuses to compile if T is not constructible from the parameter given, so I'm not sure how this complex circumlocution will help you "avoid null pointers".

    Regardless, a simple way to make choosing the second function template a compile-time error is to explicitly delete it.

    template<typename T, typename... Us>
    std::enable_if_t< std::is_constructible<T, Us...>::value == false, T * >
    create_if_constructible(Us... args) = delete;
    

    Alternatively, if you are partial to static_asserts, perhaps because of the custom error message, you must ensure that there is theoretically a way to generate a valid instantiation of your template. That means that 1) what you are static_asserting on must depend on a template argument, and 2) there must be theoretically a way for the condition to be true. A simple way is to use an auxiliary template:

    template<class> class always_false : std::false_type {};
    
    template<typename T, typename... Us>
    std::enable_if_t< std::is_constructible<T, Us...>::value == false, T * >
    create_if_constructible(Us... args) { 
       static_assert( always_false<T>::value, "Class T constructor does not match argument list.");
       return nullptr; 
    }
    

    The key point here is that the compiler cannot assume that always_false<T>::value is always false because it is always possible that there's a specialization later that sets it to true, and so it is not allowed to reject this at template definition time.

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