模板别名和因名称
Template aliases and dependent names
在思考 crtp 如何改进的同时,在 c 11 中,我以以下代码结尾:
template <typename Derived, typename Delayer>
struct derived_value_type
{
typedef typename Derived::value_type type;
};
template <typename Derived>
struct base
{
template <typename Delayer = void>
typename derived_value_type<Derived, Delayer>::type
foo(){ return {}; }
};
struct derived : base<derived>
{
typedef int value_type;
};
#include <iostream>
#include <typeinfo>
int main()
{
derived d;
auto bar = d.foo();
std::cout << typeid(bar).name() << ':' << bar << std::endl;
}
我相信先前的代码是标准符合的,并且它可以与主要编译器进行编译和合作(导致i:0
)。但是,当我使用模板别名时,由于derived
不完整,我会遇到汇编错误:
template <typename Derived, typename Delayer>
using derived_value_type = typename Derived::value_type;
/*...*/
template <typename Delayer = void>
derived_value_type<Derived, Delayer>
foo(){ return {}; }
这是编译器错误,还是编译器可以确定Delayer
没有真正的依赖性的事实意味着模板别名不是依赖类型?标准中在哪里指定?
类模板和函数模板是实例化的,但是别名模板是简单地取代的。通过摆脱会员名称type
,您将失去调用依赖名称查找规则的机会。
[N3285] 14.5.7p2:
当A template-id 指的是别名模板的专业化时,它等同于通过替换其 template-arguments 获得的相关类型>模板模板中的模板 - 参数。
所以在第一种情况下,您有:
struct derived
的定义需要base<derived>
的隐式实例化。在此实例化期间,我们发现base<derived>
具有成员函数模板:
template <typename Delayer=void>
typename derived_value_type<derived, Delayer>::type foo();
返回类型是依赖的,因此尚未查找type
,也没有实例化derived_value_type
的专业化。实例化完成,base<derived>
和derived
现在都是完整的类型。
在main
中,表达式d.foo()
需要base<derived>::foo<void>()
的隐式实例化。现在,查找typename derived_value_type<derived, void>::type
的名称,沿途实例化derived_value_type<derived, void>
。发现返回类型为int
。
在第二种情况下, derived_value_type
不是一个因名称,因此在模板base<D>
的定义下绑定到您的别名模板声明。编译器可以在模板定义或类的每个实例化期间进行别名替代,但是无论哪种方式,您都可以获得等同的类模板。
template <typename Derived>
struct base
{
template <typename Delayer = void>
typename Derived::value_type
foo(){ return {}; }
};
struct derived
的定义需要base<derived>
的隐式实例化。在此实例化过程中,我们发现base<derived>
具有成员函数模板:
template <typename Delayer=void>
typename derived::value_type foo();
但是derived::value_type
不依赖,derived
是不完整的类型,因此代码不正确。
- 部分定义/别名模板模板参数
- 如何在C++20中创建模板别名的推导指南
- 告诉c++编译器该参数没有别名
- boost::spirit::karma 替代生成器,带有 boost::variant 由字符串和字符串别名组成
- 继承模板类中的类型别名
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 为什么 GCC 在使用类型别名时处理 const reinterpret_cast不同?
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 为什么我们不能重复使用具有不同模板参数的别名模板标识符?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 如何使用类型别名从模板化类中隐藏模板列表
- 模板模板参数和模板别名:编译器错误?
- 使用定义函数模板别名
- 为模板参数包添加别名
- 如何检测类型类型别名?
- C++类型别名,其中值被替换
- C++使用默认模板参数键入别名和转发声明
- 在Qt中注册自定义元类型的别名类型
- 缺少别名模板C++参数列表
- 使用外部定义的模板类型作为模板参数的更通用模板的模板别名