为什么SFINAE失败?

问题描述 投票:0回答:2
struct BLA
{

};


template<typename T>
class DUMMY
{
public:
    DUMMY() = default;

    template<typename U = T, typename = void>
    void someFunction()
    {
        std::cout << std::is_same<U, BLA>::value << "\n";
        std::cout << "someFunction() - DEFAULT\n";
    }

    template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
    void someFunction()
    {
        std::cout << "someFunction()\n";
    }
};


int main()
{
    DUMMY<BLA> dummy;

    dummy.someFunction();
}

为什么此SFINAE代码调用显示“ someFunction()-DEFAULT”的someFunction()?它应该调用另一个。显然,std :: is_same :: value是true。

c++ sfinae
2个回答
0
投票

我正在写新答案,因为它不适合发表评论。除了@ Jarod42。

似乎您认为

template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>

替换为

template<typename U = T, typename = void>

但不是。替代

template<typename U = T, void>

因此,您应该将其声明为

template<typename U = T, typename = typename std::enable_if<std::is_same<U, BLA>::value, void>::type>

因为您使用的typename用于指定类型是从属类型,而不是用于模板参数声明。但是无论如何,它们都不起作用。一个静默删除格式不正确的代码,另一个导致相同功能的多个声明。

在您发表评论后,我尝试解释更详细。

template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>
void someFunction()
{
    std::cout << "someFunction()\n";
}

[如果为T == BLA,则U变为BLA,并且使std::is_same< U , BLA>::value true。所以结果看起来像这样

template<typename U = BLA, void>

[如果为T == NotBlaType,则U变为BLA并成为std::is_same<U,BLA>::value。因此结果看起来又像这样

template<typename U = NotBlaType, void>

但是在两种情况下,均未声明该函数。因为不能将void用作non-type template parameter

但是如果我们将void更改为int,则可以使用。这就是int起作用的原因。

[template<void = 2>不合法。

template<int = 2>是合法的。

使声明有效后,应有条件地切换函数的声明。这就是@ Jarod42答案中的两个函数都具有std::enable_if来评估彼此求反的原因。


2
投票

template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, void>::type>将会导致(正确替换)template<typename U = T, void>无效。

您可能会更改为

template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, int>::type = 0>

但是然后,这两个功能都是可行的,因此模棱两可。

所以,您最终可能会这样做

    template<typename U = T, typename std::enable_if<!std::is_same<U, BLA>::value, int>::type = 0>
    void someFunction()
    {
        std::cout << std::is_same<U, BLA>::value << "\n";
        std::cout << "someFunction() - DEFAULT\n";
    }

    template<typename U = T, typename std::enable_if<std::is_same<U, BLA>::value, int>::type = 0>
    void someFunction()
    {
        std::cout << "someFunction()\n";
    }

在C ++ 17中,更容易做到

    void someFunction()
    {
        if constexpr (std::is_same<U, BLA>::value) {
            std::cout << "someFunction()\n";
        } else {
            std::cout << std::is_same<U, BLA>::value << "\n";
            std::cout << "someFunction() - DEFAULT\n";
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.