Question

One could write a template dessigned to be specialized explicitly by the user, adding some useful error message on the default template:

template<typename T>
struct foo
{
    static_assert( sizeof(T) != sizeof(T) , "Please specialize foo for your type" );
};

Since the always-false condition depends on a template parameter the evaluation of that assert will be done during template instantation only, exactly what we want.

Now consider the inverse case: We allow the user to use a generic version of the template, but disallow him to use an specific instantation. For example:

template<typename T>
struct bar
{
    /* something useful for the user */
};

template<>
struct bar<char>
{
    static_assert( false , "No, you can't instantiate bar with char" );
};

Of course that doesn't work because the assertion doesn't depend on a template parameter, the compilation will fail even if the user doesn't instantiate bar<char>.

My question is: Is there any way to put off the evaluation of that kind of assert expression until template instantation?

EDIT: A more complex example:

template<typename T>
struct quux
{
    /* something useful for the user */
};

/* This specialization is defined to reject any instance of quux which uses a 
 * template with bool as parameter 
 */
template<template<typename> class T>
struct quux<T<bool>>
{
    static_assert( false , 
                   "Please don't use quux with a template with a bool parameter" );
};
Was it helpful?

Solution

No need for separate specialization:

template<typename T>
struct bar
{
    static_assert( !std::is_same<T, char>::value,
        "No, you can't instantiate bar with char" );
};

EDIT: In response to your edit, again a similar thing:

template<template<typename> class T, typename U>
struct quux<T<U>>
{
    static_assert( !std::is_same<U, bool>::value , 
                   "Please don't use quux with a template with a bool parameter" );
};

OTHER TIPS

You could add another dummy template parameter:

#include <type_traits>

template<typename T,typename=void>
struct bar
{
    /* something useful for the user */
};

template<typename U>
struct bar<char,U>
{
    static_assert( std::is_same<U,void>::value && false, "No, you can't instantiate bar with char" );
};

int main()
{
    bar<int> b;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top