clang++ - treat template class name as template in the class scope

我只是一个虾纸丫 提交于 2019-12-20 01:03:35

问题


It seems that clang++ (I tried clang 3.2) treats the name of a template class as a instantiated class, not a template for any occurence within the class scope. For example, the following codes

template <template <class> class T>
class A {};

template <typename T>
class B {
    A<B> member;
   // ^---- clang++ treats B as an instantiated class
         // but I want it to be a template here
         // this code could compile in g++
};

int main()
{
    B<int> b;
    return 0;
}

What should I do to compile that?


回答1:


C++03

Resolving B that way (called the injected-class-name, an implicitly-declared member of every class including template instantiations) is intended as a convenience. I've never seen it get in the way like that!

To work around, qualify the name by adding :: before it (and if necessary, the name of the namespace).

template <typename T>
class B {
    A< ::B> member; // whitespace required to prevent digraph; see comments
};

C++11

C++11 §14.6.1/1 specifies (emphasis mine)

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 with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type- specifier of a friend class template declaration, 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 <>.

Therefore, if this problem occurs under C++11 it is a compiler bug. Workaround as above.

Note — for comparison, the corresponding paragraph in C++03 is

Like normal (non-template) classes, class templates have an injected-class-name (clause 9). The injected- class-name can be used with or without a template-argument-list. When it is used without a template- argument-list, it is equivalent to the injected-class-name followed by the template-parameters of the class template enclosed in <>. When it is used with a template-argument-list, it refers to the specified class template specialization, which could be the current specialization or another specialization.

As you can see, there's already one special case allowing the identifier to be a class or template, depending on whether it occurs in a template-name. They just added a couple more cases.




回答2:


This is nonconformant behavior as of C++11 because C++11 says that the injected class name (which is a name automatically declared within the class body) is a template when it is passed to a template template parameter. So your code should only fail in a C++03 implementation.

However there is no need to open a bug report about this now. I have already done it way back.



来源:https://stackoverflow.com/questions/14291438/clang-treat-template-class-name-as-template-in-the-class-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!