SFINAE 不适用于非类型模板类

Nol*_*uck 4 c++ templates sfinae

我想使用 SFINAE 选择要在具有非类型参数的模板类中编译的特定函数,以下是我的操作方法:

#include<iostream>
#include<type_traits>
template <bool T>
struct is_right
{
    template <class Q = std::bool_constant<T>>
    typename std::enable_if<std::is_same<Q, std::bool_constant<true>>::value, bool>::type check()
    {
        return true;
    }

    template <class Q = std::bool_constant<!T>>
    typename std::enable_if<std::is_same<Q, std::bool_constant<false>>::value, bool>::type check()
    {
        return false;
    }
};

int main() {
    is_right<false> is_fs;
    is_right<true> is_ri;
    if(!is_fs.check() && is_ri.check()){
        std::cout << "It is right!" << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我使用 c++17 标准用 g++ 8.1.0 编译它。但编译器给我一个错误,说“没有匹配的函数来调用‘is_right::check()’”。

但是,如果我只是用类型参数替换非类型模板参数,它会起作用:

#include<iostream>
#include<type_traits>
template <class T>
struct is_right
{
    template <class Q = T>
    typename std::enable_if<std::is_same<Q, std::bool_constant<true>>::value, bool>::type check()
    {
        return true;
    }

    template <class Q = T>
    typename std::enable_if<std::is_same<Q, std::bool_constant<false>>::value, bool>::type check()
    {
        return false;
    }
};

int main() {
    is_right<std::bool_constant<false>> is_fs;
    is_right<std::bool_constant<true>> is_ri;
    if(!is_fs.check() && is_ri.check()){
        std::cout << "It is right!" << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它们之间有什么本质区别吗?

IlC*_*ano 5

第二个函数的默认模板参数check是错误的,它应该是std::bool_constant<T>而不是std::bool_constant<!T>

该调用is_fs.check()没有匹配的函数,因为您正在is_same<bool_constant<false>, bool_constant<true>>第一个重载和is_same<bool_constant<true>, bool_constant<false>>第二个重载中进行测试。


另请注意,现在的调用is_ri.check()是不明确的,因为这两个check函数在is_right<true>.