模板别名和相关名称 [英] Template aliases and dependent names

查看:110
本文介绍了模板别名和相关名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在考虑如何在 C ++ 11 中改进 CRTP 的同时,我以以下代码结尾:

While thinking how CRTP can be improved in C++11, I ended with the following code:

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不完整而导致编译错误:

I believe the previous code to be standard conformant, and it compiles and works with the major compilers (resulting in i:0). However, when I use a template alias instead, I get a compilation error due to derived being incomplete:

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没有真正的依赖关系这一事实是否意味着模板别名不是依赖类型?在标准中在哪里指定?

Is this a compiler bug, or does the fact that the compiler can determinate that there is no real dependency with Delayer mean that the template alias is not a dependent type? Where is this specified in the standard?

推荐答案

实例化了类模板和函数模板,但仅替换了别名模板.而且,通过删除成员名称type,您将失去调用依赖名称查找规则的机会.

Class templates and function templates are instantiated, but alias templates are simply substituted. And by getting rid of the member name type, you lose a chance at invoking the dependent name lookup rules.

[N3285] 14.5.7p2:

[N3285] 14.5.7p2:

template-id 指代别名模板的特殊化时,它等同于通过将其 template-arguments 替换为而获得的关联类型.别名模板的 type-id 中的> template-parameters .

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

因此,在第一种情况下,您具有:

So in the first case, you have:

struct derived的定义要求base<derived>的隐式实例化.在此实例化期间,我们发现base<derived>具有成员函数模板:

The definition of struct derived requires the implicit instantiation of base<derived>. During this instantiation, we discover base<derived> has a member function template:

template <typename Delayer=void>
typename derived_value_type<derived, Delayer>::type foo();

返回类型是依赖的,因此尚未查找type,并且没有实例化derived_value_type的特殊化.实例化完成,并且base<derived>derived现在都是完整的类型.

The return type is dependent, so type is not yet looked up, and no specialization of derived_value_type is instantiated. The instantiation finishes, and base<derived> and derived are both now complete types.

main中,表达式d.foo()需要base<derived>::foo<void>()的隐式实例化.现在查找名称typename derived_value_type<derived, void>::type,并沿途实例化derived_value_type<derived, void>.返回类型为int.

In main, the expression d.foo() requires the implicit instantiation of base<derived>::foo<void>(). Now the name typename derived_value_type<derived, void>::type is looked up, instantiating derived_value_type<derived, void> along the way. The return type is found to be int.

在第二种情况下,derived_value_type不是从属名称,因此绑定到模板base<D>定义中的别名模板声明.编译器可以在模板定义时或在类的每个实例化期间进行别名替换,但是可以通过两种方式获得等效于以下内容的类模板:

In the second case, derived_value_type is not a dependent name, so is bound to your alias template declaration at the definition of template base<D>. The compiler could do the alias substitution either at the template definition or during each instantiation of the class, but either way you get a class template equivalent to:

template <typename Derived>
struct base
{
  template <typename Delayer = void>
  typename Derived::value_type
  foo(){ return {}; }
};

struct derived的定义要求base<derived>的隐式实例化.在此实例化期间,我们发现base<derived>具有成员函数模板:

The definition of struct derived requires the implicit instantiation of base<derived>. During this instantiation, we discover base<derived> has a member function template:

template <typename Delayer=void>
typename derived::value_type foo();

但是derived::value_type不依赖,并且derived是不完整的类型,因此代码格式错误.

But derived::value_type is not dependent, and derived is an incomplete type, so the code is ill-formed.

这篇关于模板别名和相关名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆