Class 模板别名不应该在生成的符号中可见,是吗?

Class templates alias should not be visible in generated symbols, do they?

godbolt 中编译此代码段时,大多数编译器生成两种不同的 get 方法(程序集中的不同符号 window):

template<typename  T> 
struct Field { T impl; };

template<typename  T> 
using CurrentField = Field<T>;

template<template <typename> class F> 
struct Encompassing { F<int> member; };


auto get(Encompassing<Field> const& instance)
{
    return instance.member.impl;
}
auto get(Encompassing<CurrentField> const& instance)
{
    return instance.member.impl;
}

我在符号中看到 CurrentField,即使它是别名。只有 gcc 抱怨重新定义(如预期的那样)。

type_alias 上的 C++ 参考说

It does not introduce a new type

所以我认为它不应该像这样,我错了吗?

实际上,大多数编译器的行为似乎是将别名模板替换为 class 特征,例如

template<typename T>
struct CurrentField
{
 alias type = Field<T> ;
};

编辑:

这是我在 Godbolt 上尝试实现的更具代表性的示例。请注意,它编译是因为只有一个源并且没有 linking,但 msvc 程序集显示它生成了预实例化签名和用户调用签名。

有4个部分: 1. 具有多种模板的容器库,如 StackFieldHeapField, 2. 一个实用程序库,其中包含大小等成员方法,并将字段作为模板参数(如您提出的第二个解决方法), 3. 不同领域的实现在c++中被隐藏和预实例化 4. 用户 link 他们针对这个库的应用程序 A 和 B,使用像 AFieldBField 这样的别名。它适用于 gcc,但 link 在 msvc 中失败,因为我的预实例化实现的签名与用户调用不匹配

别名模板确实没有引入新类型。但是您的 class 模板将模板作为参数,而不是类型。 FieldCurrentField 都是模板。所以这归结为 CurrentField 应该算作与 Field 相同的模板还是单独的模板的问题。这是CWG issue 1286. See also 。 GCC遵循第一种解释,clang和MSVC遵循第二种…

一种解决方法似乎是通过辅助模板来打破 CurrentFieldField 的直接映射:

    template <typename T>
    struct CurrentFieldHelper { using type = Field<T>; };

    template <typename T> 
    using CurrentField = typename CurrentFieldHelper<T>::type;

工作示例here

恐怕没有办法实现相反的效果,即让所有编译器将 get(Encompassing<CurrentField> const &) 视为与 get(Encompassing<Field> const &) 相同的函数。在不了解您的实际代码的情况下,很难针对这个特定问题提出解决方法。一个可能适用于您的实际代码的简单解决方案是制作 size 一个解包 instance.member 的函数模板,然后将其转发给执行实际工作的通用函数:

template <template <typename> class F> 
auto size(Encompassing<F> const& instance)
{
    return size(instance.member);
}