为什么推导方法模板不能直接使用class个模板呢? SFINAE

Why can't we use class templates directly for deducing method templates? SFINAE

此代码有效:

// g++ -std=c++11
// (or)
// clang++ -std=c++11

#include <iostream>

template <class T>
struct Tester
{
    template <class S = T, class = decltype(S())>
    static void Test (int && k)
    {
        std::cout << "Default constructible" << std::endl;
    }

    static void Test (...)
    {
        std::cout << "Not default constructible" << std::endl;
    }
};

struct HasDefaultConstructor
{
    HasDefaultConstructor() = default;
};

struct NoDefaultConstructor
{
    NoDefaultConstructor() = delete;
};

int main ()
{   
    Tester<HasDefaultConstructor>::Test(int());
    Tester<NoDefaultConstructor>::Test(int());

    return 0;
}

但是我想明白为什么我需要为间接模板推导设置S template <class S = T, class = decltype(S())>

我更愿意通过使用 template <class = decltype(T())> 来更简单地完成它,但是在 gcc 中这会导致错误的输出:所有对 Test 方法的调用都转到第一个;在 clang 中,这会导致错误 call to deleted constructor of 'NoDefaultConstructor'(感谢 HolyBlackCat 在这里指出 clang 编译错误)。

为什么?强制我们间接引用 class 模板的编译器/c++ 标准的过程是什么?

这是因为您首先实例化了模板classTester。因此,要求 class = decltype(T()) 成为对模板 class Tester<T> 本身的要求。因此,如果不满足,则模板 class 格式错误。 编辑:想象一下ypu实际上想写一个模板函数,以X作为模板参数并使用class X = decltype(T())作为默认条目?编译器如何区分它和 SFINAE 的东西?

间接推导template <class S = T, class = decltype(S())>将其转化为对模板函数Test的要求,而不是整个class.

这是技术原因。是的,没有人喜欢 SFINEA 和函数元编程,这就是为什么在 C++20 中引入概念并开发 constexpr 编程的原因。