TransWikia.com

What is the advantage of std::enable_if over static_assert for class templates?

Stack Overflow Asked by Reizo on October 11, 2020

I was wondering about the advantage of std::enable_if over static_asserts to prevent template instantiation. This answer suggests, that std::enable_if allows SFINAE, which is a convincing argument in the case of function templates.

However is this argument legitimate for class templates (and variable templates)? As far as I know, there is no overload resolution involved there, making SFINAE – again, as far as I know – not relevant, but I might be wrong. If so, can you name an example?

If not, I assume static_assert to be the better solution for the given issue (preventing template instantiation) in the case of class templates, since it’s arguably more explicit, concise and readable and allows a custom error message. Is that correct or am I missing a point other than SFINAE?

3 Answers

Example of how to overload classes using SFINAE:

#include <type_traits>
#include <iostream>

template <typename, typename = void>
struct Foo;

template <typename Bar>
struct Foo <Bar, typename std::enable_if<std::is_same<Bar,int>::value>::type>
{
    Foo ()
    {
        std::cout << "Hello ";
    }
};

template <typename Bar>
struct Foo <Bar, typename std::enable_if<std::is_same<Bar,bool>::value>::type>
{
    Foo ()
    {
        std::cout << "world!n";
    }
};

int main()
{
    Foo<int>();
    Foo<bool>();
}

For cases where you don't want to do overloading but still want to restrict to a set of types, I agree that:

template <typename Bar>
class Foo
{
    static_assert(
        std::is_same<Bar,int>::value || 
        std::is_same<Bar,bool>::value, 
        "Bar must be bool or int");
    
    // class stuff
};

...is clearer and simpler than:

template <typename Bar,
    typename std::enable_if<
    std::is_same<Bar,int>::value ||
    std::is_same<Bar,bool>::value,
    bool>::type = true>
class Foo
{
    // class stuff
};

...especially because with the second option the compiler refers to Foo objects with their first argument and their second argument (true, in our case), which can be mysterious to the user. Also, it's more messy if you want a header to handle the class with only a light-weight declaration of it (see how to do that here).

Correct answer by Elliott on October 11, 2020

std::enabled_if is used in SFIANE for specialization of template classes, methods and .... static_assert is used for checking a contract at compile time, and providing a useful error message.

Answered by apramc on October 11, 2020

However is this argument legitimate for class templates (and variable templates)? As far as I know, there is no overload resolution involved there, making SFINAE - again, as far as I know - not relevant, but I might be wrong. If so, can you name an example?

You can specialise class templates and SFINAE may be used to pick between specialisations. It will also prevent instantiation of such (by then, possibly ill-formed) class / its specialisation, instead of failing to compile due to static_assert.

Answered by Fureeish on October 11, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP