对于类模板,std::enable_if 相对于 static_assert 的优势是什么?

Rei*_*izo 3 c++ templates static-assert enable-if class-template

我想知道std::enable_ifoverstatic_asserts防止模板实例化的优势。这个答案表明,这std::enable_if允许SFINAE,这在函数模板的情况下是一个令人信服的论点。

然而,这个论点对于类模板(和变量模板)是否合法?据我所知,那里不涉及重载决议,这使得 SFINAE - 再次,据我所知 - 不相关,但我可能是错的。如果是这样,你能举一个例子吗?

如果不是,我认为static_assert在类模板的情况下是给定问题(防止模板实例化)的更好解决方案,因为它可以说更明确、简洁和可读,并允许自定义错误消息。这是正确的还是我错过了 SFINAE 以外的一点?

Ell*_*ith 5

如何使用 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>();
}
Run Code Online (Sandbox Code Playgroud)

对于您不想重载但仍想限制为一组类型的情况,我同意:

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
};
Run Code Online (Sandbox Code Playgroud)

...比以下内容更清晰、更简单:

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
};
Run Code Online (Sandbox Code Playgroud)

...特别是因为使用第二个选项时,编译器Foo使用它们的第一个参数第二个参数(true在我们的例子中)来引用对象,这对用户来说可能是神秘的。此外,如果您想要一个头文件来处理该类,并且只对其进行轻量级声明,则会更加混乱(请参阅如何在此处执行此操作)。