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

标签 c++ c++17

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

  1. 这是合法的 C++ 代码吗?为什么?或者为什么不呢?
  2. 是否有适用于两种编译器的解决方法(或正确的替代方法)?
#include <tuple>

template<typename>
struct first_type;

template<template<typename, typename...> typename T, typename T1, typename... Ts>
struct first_type<T<T1, Ts...>>
{ using type = T1; };

template<typename T>
using first_type_t = typename first_type<T>::type;

using tuple_type1 = first_type_t<std::tuple<int, int, double>>;

Live example


应要求,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;
       ^

总结:

  • 由 IWonderWhatThisAPIDoes 回答;要完全避免编译器差异,只需放弃模板化模板参数至少具有单一类型的要求。
  • 正如 Nathan Oliver 所指出的;如果你需要元组的第一种类型(或者任何给定索引的类型),只需使用 std::tuple_element元函数代替。
  • 正如 HolyBlackCat 所指出的;似乎 Clang 对模板化模板参数执行的裁决比标准的技术要求更严格。可以通过传递 -frelaxed-template-template-args 编译器标志来禁用此行为。

最佳答案

暂时将您的结构声明更改为(从而摆脱不完整的类型):

template<typename>
struct first_type {};

将您遇到的错误更改为:

no type named 'type' in 'first_type<std::tuple<int, int, double>>'

这给了我们有值(value)的信息:编译器选择了模板的通用版本,这意味着 Clang 不认为元组是有效的 template<typename,typename...>class实例化 first_type with (这是真的 - template<typename,typename...>class 接受一个或多个参数,而元组也可以为空)。正如评论中所指出的,这对标准本身并不重要,但是 Clang rejects it on purpose .

一个元组是一个template<typename...>class , 所以...

template<template<typename...> typename T, typename T1, typename... Ts>
struct first_type<T<T1, Ts...>> {
    using type = T1;
};

关于c++ - 编译器与简单元函数的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67691007/

相关文章:

c++ - 使用上一次调用的结果递归调用每个元组成员

c++ - 动态扩展指针数组

c++ - std::chrono::duration::max() 不适用于线程支持库

c++ - 如何流式传输 std::variant<...,...>

c++ - 从 vector 中提取 uint8_t* 子集<uint8_t>

c++ - 在这个例子中,std::variant 是如何变成 valueless_by_exception 的?

c++ - vector 删除功能不起作用(简单代码)

c++ - 如何在 GTK+ 中创建多个但独立的模式对话框?

c++ - 用memcpy复制一个class对象是对的吗?

c++ - 有没有办法拥有模板的别名并保留类模板参数推导?