代码之家  ›  专栏  ›  技术社区  ›  Jarod42

需要不同的类型,具体取决于实例化点

  •  3
  • Jarod42  · 技术社区  · 6 年前

    #include <type_traits>
    
    template <typename T, typename Enabler = void>
    struct is_complete : std::false_type {};
    
    template <typename T>
    struct is_complete<T, std::void_t<decltype(sizeof(T) != 0)>> : std::true_type {};
    
    class X;
    
    static_assert(!is_complete<X>::type{}); // incomplete type
    
    class X {};
    
    static_assert(!is_complete<X>::type{}); // complete, but already instantiated
    

    Demo

    注意 :假设 sizeof(T) != 0 对于完整性特征有效(因为没有类型可以具有 sizeof(T) == 0 ,使用其他常量将强制为这些特征找到更好的名称:-)

    Is a specialization implicitly instantiated if it has already been implicitly instantiated? ,其中程序被声明为格式错误的程序,无需诊断(NDR),作为 方法 is_complete_helper<X>::test<X>

    参考资料似乎会使程序格式不正确,但据我所知:

    在假设的实例化中对这种构造的解释不同于在模板的任何实际实例化中对相应构造的解释。

    我错了?或者不幸的是这个程序是正确的。

    1 回复  |  直到 6 年前
        1
  •  7
  •   Barry    6 年前

    我预计以下是格式错误的NDR,但似乎不是:-(

    你不能用程序编译(和运行)的事实来证明它不是格式错误的,NDR。就像你不能用看似有效的程序输出来证明它没有未定义的行为一样。

    也就是说,这里的相关规则是 [temp.point]/8 :

    类模板的专门化在翻译单元中最多有一个实例化点。任何模板的专门化都可以在多个翻译单元中有实例化点。如果两个不同的实例化点根据一个定义规则赋予一个模板专门化不同的含义,则该程序是格式错误的,不需要诊断。

    我们只有一个实例点 is_complete<X> :就在第一个 static_assert

    但是,如果我们把它分开:

    // a.cpp
    struct X;
    static_assert(!is_complete<X>::value);
    
    // b.cpp
    struct X { };
    static_assert(is_complete<X>::value);
    


    注意,你不需要 sizeof(T) != 0 . 只是 sizeof(T) 很好。你不能接受 sizeof 一个不完整的类型,所以你只需要检查一下 尺寸(T)