为什么我们不能直接使用类模板来推导方法模板? FINAE

时间:2019-12-21 10:17:26

标签: c++ templates metaprogramming 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编译错误)。

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

1 个答案:

答案 0 :(得分:2)

这是因为您首先实例化了模板类Tester。因此,需求class = decltype(T())成为模板类Tester<T>本身的需求。因此,如果不满意,则模板类格式错误。 编辑:假设ypu确实想编写一个以X作为模板参数并使用class X = decltype(T())作为默认条目的模板函数?除了SFINAE的东西,编译器如何告诉它?

间接推论template <class S = T, class = decltype(S())>将其转换为模板函数Test的需求,而不是整个类。

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