【问题标题】:Alias of a template. Who's right?模板的别名。谁是对的?
【发布时间】:2019-11-09 18:42:11
【问题描述】:

下面的代码看似合理,但在两个主要编译器上都不起作用

#include <type_traits>

template<template<class> class Tmp>
struct S{
    template<class T>
    using tmp_t = Tmp<T>;

    static_assert(std::is_same_v< S<tmp_t>, S<Tmp> >,
        "Not same?? How come?");
};

template<class> struct Dummy{};

template struct S<Dummy>;

gcc7.1 开头可以编译(https://godbolt.org/z/DjAcgP

叮当https://godbolt.org/z/ewBbZJ

msvc (https://godbolt.org/z/6ZmQwj)
没有这样做

此代码符合标准吗?

【问题讨论】:

标签: c++ language-lawyer


【解决方案1】:

GCC 是错误的。 tmp_t 声明了一个新模板(准确地说是别名模板)。而且这个新模板不同于任何其他模板。

[temp.alias](强调我的)

1 一个模板声明,其中的声明是 alias-declaration 将标识符声明为别名模板。一个 别名模板是一系列类型的名称。 名称 别名模板是模板名称

粗体字表示tmp_t 指的是新的别名模板,它不指代别名的特化可能被定义为的任何内容。因此S&lt;tmp_t&gt;S&lt;Tmp&gt; 是两个具有不同 参数的特化。

相比之下,有一些特殊规则使别名模板特化代表它们别名的确切内容

2 当模板 ID 指代别名的特化时 模板,就相当于得到的关联类型 用它的模板参数替换模板参数 别名模板的 type-id。

所以 while 模板 ID tmp_t&lt;foo&gt;Tmp&lt;foo&gt; 的含义完全相同,tmp_t 本身(不带参数)不是模板 ID(它没有命名专业化)。相反,它将模板命名为不同的实体。

【讨论】:

  • 那么无限递归呢?在实例化std::is_same之前,应该先实例化S&lt;tmp_t&gt;,然后再实例化S&lt;tmp_t&gt;,以此类推……
  • @Evg - 我不确定它是否需要实例化。 S&lt;tmp_t&gt; 是类型名称,它的使用方式在我看来并不需要完整的类定义。出于这个原因,它不应该真正被递归实例化。我基于timsong-cpp.github.io/cppwp/n4659/temp.inst#1
  • 因此,鉴于S 的专业化,我无法获得模板Tmp ......这真是太糟糕了。我正在考虑一个具有 sourcedestination 参数的转换器类,但我想我必须朝另一个方向挖掘。
  • @Adler - 恐怕是这样。我不知道有任何方法可以公开Tmp 本身以供操纵。
  • @idclev463035818 - 我相信gcc.gnu.org/bugzilla/show_bug.cgi?id=92060 就是那个。
猜你喜欢
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
相关资源
最近更新 更多