Variadic template template wrapper:奇怪的编译器错误,可能是错误

Variadic template template wrapper: weird compilers errors, possibly bugs

在多年的模板元编程实践中,我遇到过各种奇怪的编译器错误和错误。但是对于这个,我必须说我有些困惑。我不知道哪个编译器是正确的:gccclangmsvcintel 都给出了不同的结果(听起来可能令人惊讶,只有 intel 编译代码没有错误)。更令人惊讶的是,它不依赖任何新的 C++ 功能,因为只涉及 C++11


代码本身会说话,因为它相对简单。它仅包含一个可变参数模板模板包装器和一个可变参数内部实体,该实体可以是结构或别名模板。无论出于何种原因,别名模板版本 returns 在构造它的实例时对某些编译器来说是一个错误:

#include <type_traits>

template <class T1, class T2, class T3> 
struct ternary {};

template <template <class...> class Template, class... Types>
struct template_struct {
    template <class... Args>
    struct type: Template<Types..., Args...> {};
};

template <template <class...> class Template, class... Types>
struct template_alias {
    template <class... Args>
    using type = Template<Types..., Args...>;
};

现在测试:

int main(int, char**) {
    using ts0 = template_struct<ternary>;                           // OK
    using ts1 = template_struct<ternary, bool>;                     // OK
    using ts2 = template_struct<ternary, bool, char>;               // OK
    using ts3 = template_struct<ternary, bool, char, int>;          // OK
    using ts4 = template_struct<ternary, bool, char, int, double>;  // OK
    ts0 s0;     // OK
    ts1 s1;     // OK
    ts2 s2;     // OK
    ts3 s3;     // OK    
    ts4 s4;     // OK
    using ta0 = template_alias<ternary>;                            // OK
    using ta1 = template_alias<ternary, bool>;                      // OK
    using ta2 = template_alias<ternary, bool, char>;                // OK
    using ta3 = template_alias<ternary, bool, char, int>;           // OK
    using ta4 = template_alias<ternary, bool, char, int, double>;   // OK
    ta0 a0;     // OK
    ta1 a1;     // OK
    ta2 a2;     // OK
    ta3 a3;     // GCC, INTEL => OK | CLANG, MSVC => ERROR: WAIT WHAT ?!?!
    ta4 a4;     // INTEL => OK | GCC, CLANG, MSVC => ERROR
    return 0;
}

代码在编译器资源管理器上可用:https://godbolt.org/z/3ndYMWvfs


问题:发生了什么事?哪个编译器是正确的?标准怎么说?是编译器错误吗?

所有编译器都是正确的,两个失败的测试是 ill-formed NDR(“不需要诊断”)。

> 3 参数案例是 ill-formed NDR 因为 [temp.res.general]/6.1:

The program is ill-formed, no diagnostic required, if:

— no valid specialization can be generated for a template ... and the template is not instantiated, ...

== 3 参数案例是 ill-formed NDR 因为 [temp.res.general]/6.3:

The program is ill-formed, no diagnostic required, if:

— every valid specialization of a variadic template requires an empty template parameter pack ...

这两个 template_struct<ternary, ...> 测试似乎是合法的,因为您可以将 struct type 特化为有效的东西,而且我没有立即看到必须至少有一个有效特化的规则主要(非专用)模板。