当c++实例化方法?

When c++ instantiating method?

本文关键字:方法 实例化 c++      更新时间:2023-10-16

我正在尝试使用 gcc 和 clang 编译此代码:

#include <iostream>
#include <type_traits>

template<int N>
struct Test
{
    template<typename = std::enable_if_t<N == 1, bool>>
    void func()
    {
        std::cout << "Test::func" << std::endl;
    }
};
int main()
{
    Test<0> t;
    //t.func();
}

所以,我有一个错误:

error: no type named 'type' in 'std::__1::enable_if<false, bool>'; 'enable_if' cannot be used to 
disable this declaration
template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type;

但是如果我使用 vc++ 编译该代码,则没有错误。 那么,哪个编译器根据 c++ 标准解决了这个问题呢?

GCC和Clang在这里是正确的。

当您编写Test<0>时,N将替换为 0。在func声明中,std::enable_if_t将尝试访问不存在的成员::type。这是一个错误,因为该成员不存在,并且您不能有这样的声明。

SFINAE 的工作方式是,在重载解析期间,当编译器执行模板参数推导时,如果模板中参数的替换失败,则不会收到错误,并且该函数将从潜在的重载集中丢弃。在您的示例中,没有模板参数推导。N 已经从类模板中已知,因此,在重载解析开始之前,func 的声明格式不正确。

您的用例的潜在解决方法是:

template<int M = N, typename = std::enable_if_t<M == 1, bool>>
void func()
{
    std::cout << "Test::func" << std::endl;
}

这样,func现在依赖于函数模板参数,M ,并且 SFINAE 按预期工作。