【发布时间】:2019-11-28 10:17:14
【问题描述】:
在godbolt 中编译此片段时,大多数编译器会生成两个不同的get 方法(汇编窗口中的不同符号):
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++ 参考说
没有引入新类型
所以我认为它不应该这样,我错了吗?
实际上,大多数编译器的行为似乎就像别名模板被替换为类 Trait 一样
template<typename T>
struct CurrentField
{
alias type = Field<T> ;
};
编辑:
这是我尝试在Godbolt 上实现的目标的更具代表性的示例。请注意,它可以编译,因为只有一个源且没有链接,但 msvc 程序集显示它生成了预实例化签名和用户调用签名。
有4个部分:
1. 包含StackField 和HeapField 等多种模板的容器库,
2.具有成员方法的实用程序库,如大小,字段作为模板参数(如您提出的第二个解决方法),
3. 实现在c++中被隐藏和预实例化,用于不同的领域
4. 用户使用AField 和BField 之类的别名将他们的应用程序A 和B 链接到这个库。它适用于 gcc,但在 msvc 中链接失败,因为我的预实例化实现的签名和用户调用不匹配
【问题讨论】:
-
您可能需要添加 [language-lawyer] 标签。
标签: c++ c++11 templates language-lawyer alias