如何使用类本身内部的类名称作为模板参数? [英] How do I use the class-name inside the class itself as a template argument?

查看:91
本文介绍了如何使用类本身内部的类名称作为模板参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个模板参数的模板化类

I've got a templated class having two template paramters

template <class T, class U> class A  /* ... */

和另一个模板类,该模板类接受带有两个参数作为模板参数的模板类.

and another template class that accepts a template class with two arguments as template parameter.

template <class T, class U, template<class X, class Y> class Z>
class B
{
    typedef typename Z<T,U>::pointer pointer;
};

是否不可能在Z为A的A中创建B的实例?

Is it impossible to create an instance of B in A where Z is A?

template <class T, class U>
class A  
{
public:
  B<T,U,A> foo (void) // compiler complaining here
  {
    B<T,U,A> test; // and here
    return test;
  }
};

一个做相同事情的自由函数根本没有问题.

A free function doing the same thing isn't problematic at all.

template<class T, class U>
B<T, U, A> bar (void)
{
    B<T,U,A> test;
    return test;
}

换句话说:是否有没有我未曾接受过的规则可以阻止我将自己所在的类的名称用作模板参数?

In other words: Is there any rule I didn't fell over yet that prevents me from using the name of the class I am in as a template argument?

代码是:

template <class T, class U, template<class X, class Y> class Z>
class B
{
  typedef typename Z<T,U>::pointer pointer;
};

template <class T, class U>
class A 
{
public:
  B<T,U, A> foo (void) 
  {
    B<T,U,A> test;
    return test;
  }
};

template<class T, class U>
B<T, U, A> bar (void)
{
    B<T,U,A> test;
    return test;
}

int main (void)
{
 return 0;
}

MSVC 2012编译器给出了编译器错误3200 ./p>

And the MSVC 2012 compiler gives a Compiler Error 3200.

'A<T,U>' : invalid template argument for template parameter 'Z', expected a class template

推荐答案

您的编译器MSVC似乎遵循§14.6.2.1/1 C ++ 11中规定的一般规则:

Your compiler, MSVC, seems to follow the general rule laid down in §14.6.2.1/1 C++11:

名称是指当前实例,如果在类模板的定义中名称是...的注入类名称[...]类模板[...]

A name refers to the current instantiation if it is, [...] in the definition of a class template, [...] the injected-class name [...] of the class template [...]

在类模板 A 的定义中,可以使用名称 A ,因为它是注入"到 A .因此,著名的是,您可以使用 A 以及 A :: A 以及 A :: A :: A 等上,以指代 A .根据上面引用的规则,所有这些表达式均引用当前实例化(即特定类型,例如 A< int,float> ),而不是模板的名称 A 本身.

Inside the definition of class template A, the name A can be used because it is "injected" into the local (class) scope of A. Therefore, and famously, you can use A as well as A::A, as well as A::A::A and so on, to refer to A. By the rule quoted above, all of these expressions refer to the current instantiation (i.e. a specific type like A<int,float>), and not to the name of template A itself.

但是,在第14.6.1/1条中还有另一条规则:

However, there is another rule, in §14.6.1/1:

与普通(非模板)类一样,类模板具有注入的类名(第9条).注入的类名称可以用作模板名称或类型名称.用作模板模板参数的模板参数时,它指的是类模板本身.否则,它等效于<>中包含的类模板的模板名称及其模板参数.

Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name. When it is used [...] as a template-argument for a template template-parameter [...] it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.

(请注意,在C ++ 03中,模板模板参数没有这种例外;实际上,14.6.1/1的措词完全不同.在C ++ 03中,MSVC对规则的解释可能是正确的)

(Note that in C++03, there is no such exception for template template parameters; 14.6.1/1, in fact, is worded entirely differently. Under C++03, MSVC's interpretation of the rules was probably correct.)

但是,在成员声明中给出了C ++ 11规则

Given the C++11 rule, however, in the member declaration

B<T,U,A> test;

A 的定义中,名称 A 显然用作模板模板参数的参数,因此必须解释为模板名称,而不是类型名称指当前实例.

inside the definition of A, the name A is clearly used as an argument for a template template parameter and therefore must be interpreted as template name, not as type name referring to the current instantiation.

但是,在这种情况下,编译器常常会混淆.有两种有效的方法来告诉他们如何解释 A :

However, it is not uncommon that compilers are confused in situations like this. There are two valid ways to tell them how to interpret A:

  1. 使用所谓的正常名称 :: A 而不是注入的名称:

B<T,U,::A> test;

由于§14.6.1/5(在C ++ 03中为14.6.1/2c),因此有可能:

This is possible because of §14.6.1/5 (which was 14.6.1/2c in C++03):

使用模板的常规名称(即,来自封闭范围的名称,而不是注入的类名称)时,它始终引用类模板本身,而不是模板的特殊化.[...]

When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name) is used, it always refers to the class template itself and not a specialization of the template. [...]

  • 显式使用注入的对象,但将其指定为模板:

  • Using the injected one explicitly, but designating it as a template:

    B<T,U,A::template A> test;
    

  • 这两种方法都可以在MSVC中解决此问题.

    Both methods have been confirmed as solving this problem in MSVC.

    这篇关于如何使用类本身内部的类名称作为模板参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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