C++ 编译器与简单元函数的差异

C++ 编译器与简单元函数的差异,c++,c++17,C++,C++17,当我尝试使用以下元函数检索元组的第一种类型时,代码可以用GCC编译,但不能用Clang编译。关于这个小片段,我有两个问题 这是合法的C++代码吗?为什么?或者为什么不呢 是否有一种变通方法(或正确的替代方法)可以同时适用于这两种编译器 #包括 模板 结构优先型; 模板 结构第一类型{ 使用类型=T1; }; 模板 使用first\u type\u t=typename first\u type::type; 使用元组类型1=第一个类型; 例如: 根据请求,Clang生成的错误消息: <

当我尝试使用以下元函数检索元组的第一种类型时,代码可以用GCC编译,但不能用Clang编译。关于这个小片段,我有两个问题

这是合法的C++代码吗?为什么?或者为什么不呢
  • 是否有一种变通方法(或正确的替代方法)可以同时适用于这两种编译器
  • #包括
    模板
    结构优先型;
    模板
    结构第一类型{
    使用类型=T1;
    };
    模板
    使用first\u type\u t=typename first\u type::type;
    使用元组类型1=第一个类型;
    
    例如:


    根据请求,Clang生成的错误消息:

    <source>:12:1: error: implicit instantiation of undefined template 'first_type<std::tuple<int, int, double>>'
    using first_type_t = typename first_type<T>::type;
    ^
    <source>:14:21: note: in instantiation of template type alias 'first_type_t' requested here
    using tuple_type1 = first_type_t<std::tuple<int, int, double>>;
                        ^
    <source>:4:8: note: template is declared here
    struct first_type;
           ^
    
    :12:1:错误:未定义模板“first\u type”的隐式实例化
    使用first\u type\u t=typename first\u type::type;
    ^
    :14:21:注意:在模板类型的实例化中,此处请求的别名为“first\u type\t”
    使用元组类型1=第一个类型;
    ^
    :4:8:注意:此处声明了模板
    结构优先型;
    ^
    
    将结构声明临时更改为(从而消除不完整的类型):


    当出现差异时,通常clang是对的,MSV是错的,GCC将编译您抛出的任何东西。FWIW,您可以使用类似
    的方法来代替,比如使用first\u type\u t=typename std::tuple\u element::type
    @NathanOliver谢谢,我完全忽略了:
    templateclass T
    中的DName没有用,并且在以后重新使用时有点误导。我想你可以在修复专业化后将主模板改回不完整的状态吗?@TedLyngmo这是我答案的完成吗,还是编辑建议?@Iwonderhatthisapi有很好的洞察力!我甚至没有想到要尝试这种变化,而你的解释似乎很有道理。唯一仍然缺少的是一个更正式的语句,它揭示了GCC为什么会产生错误。如果您传递
    -frelaxed-template-args
    ,则Clang会接受这一点。由于此标志启用默认禁用的标准兼容行为,GCC实际上是正确的。@TEDLYNMO他们说这是一个突破性的更改,因为措辞有缺陷。他们似乎还在等待解决办法/
    template<typename>
    struct first_type {};
    
    no type named 'type' in 'first_type<std::tuple<int, int, double>>'
    
    template<template<typename...> typename T, typename T1, typename... Ts>
    struct first_type<T<T1, Ts...>> {
        using type = T1;
    };