Search code examples
c++classtemplatesc++17static-assert

How to make static_assert block re-usable in template classes?


Say I have a template class that makes multiple static_asserts:

template <class T>
class Foo
{
    static_assert(!std::is_const<T>::value,"");
    static_assert(!std::is_reference<T>::value,"");
    static_assert(!std::is_pointer<T>::value,"");

    //...<snip>...
}

Now say I have more template classes that need to make the same asserts.

Is there a way to make a static_assert block reusable? A "static_assert function" if you will.


Solution

  • One thing you can do is build a new trait that is a conjunction of the traits you want to check. Since you want the negation of all of those traits that would literally translate to

    template<typename T>
    using my_trait = std::conjunction<std::negation<std::is_const<T>>,
                                      std::negation<std::is_reference<T>>,
                                      std::negation<std::is_pointer<T>>>;
    
    static_assert(my_trait<int>::value, "");
    

    but having to use std::negation for every trait is/can be a pain. You can get rid of that though using std::disjunction to get an "or" of all the traits and then just negate the value in the static assert like you do which gives you

    template<typename T>
    using my_trait = std::disjunction<std::is_const<T>,
                                      std::is_reference<T>,
                                      std::is_pointer<T>>;
    
    static_assert(!my_trait<int>::value, "");