【问题标题】:When c++ instantiating method?c++什么时候实例化方法?
【发布时间】:2019-11-20 21:59:58
【问题描述】:

我正在尝试用 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++ 标准解决了这个问题?

【问题讨论】:

    标签: c++ gcc visual-c++ clang


    【解决方案1】:

    GCC 和 Clang 在这里是正确的。

    当您编写Test&lt;0&gt; 时,会将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 可以按预期工作。

    【讨论】:

    • 嗯...我想,如果我不使用函数func,那么编译器就不会为该函数实例化并生成代码。 “请注意,代码仅针对被调用的模板(成员)函数进行实例化。对于类模板,成员函数仅在使用时才被实例化。” - 这是来自 C++ Templates The Complete Guide 2nd 的引文版。
    • 模板确实不会被实例化,但它仍然需要是一个有效的函数模板声明。在这种情况下不会,声明格式不正确。您可以在未调用的模板函数的 body 中包含无效代码,但在其声明中没有(除非 SFINAE 应用,在这种情况下它不存在,因为没有替换)。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    相关资源
    最近更新 更多