How to write `is_complete` template?

前端 未结 7 609
耶瑟儿~
耶瑟儿~ 2020-11-29 07:35

After answering this question I was trying to find is_complete template in Boost library and I realized that there is no such template in Boost.TypeTraits. Why

7条回答
  •  有刺的猬
    2020-11-29 07:54

    Solving this requires performing the computation in the default argument of the trait template, as attempting to change the definition of a template violates the ODR rule (although a combination of __COUNTER__ and namespace {} can work around ODR).

    This is written in C++11 but can be adjusted to work in C++03 mode of a moderately recent C++11-compatible compiler.

    template< typename t >
    typename std::enable_if< sizeof (t), std::true_type >::type
    is_complete_fn( t * );
    
    std::false_type is_complete_fn( ... );
    
    template< typename t, bool value = decltype( is_complete_fn( (t *) nullptr ) )::value >
    struct is_complete : std::integral_constant< bool, value > {};
    

    Online demo.

    The default argument is evaluated where the template is named, so it can contextually switch between different definitions. There is no need for a different specialization and definition at each use; you only need one for true and one for false.

    The rule is given in §8.3.6/9, which applies equally to function default arguments and default template-arguments:

    Default arguments are evaluated each time the function is called.

    But beware, using this inside a template is almost sure to violate the ODR. A template instantiated on an incomplete type must not do anything differently from if it were instantiated on a complete type. I personally only want this for a static_assert.

    Incidentally, this principle may also be helpful if you want to go the other way and implement the functionality of __COUNTER__ using templates and overloading.

提交回复
热议问题