Template方法和默认模板参数

9

我的问题可以通过以下代码片段概括:

template <typename T> struct C2;

template <typename T> 
struct C1
{
  template <typename Type,
        template <typename Ti> class Container = C2>
  void m() {}
};


template <typename T> 
struct C2
{
  template <typename Type = int,
        template <typename Ti> class Container = C2> // <-- Here is the problem!
  void m() {}

};

GNU编译器版本4.8.1出现以下错误信息:

test-temp.C:16:47: error: invalid use of type ‘C2<T>’ as a default value for a template template-parameter
      template <typename Ti> class Container = C2> 

它指的是方法C2::m的默认模板参数C2。

显然(这是我的观点),编译器将>视为默认参数,而不是没有的C2。因此,当它找到该指令时,由于类型>与不匹配,它会失败。

然而,clang++对于完全相同的代码编译得很好!

我的问题:

  1. 哪个编译器是正确的?
  2. 是否有一些替代方案来使用当前版本的gnu编译器表达相同的意义?

谢谢您提前

Leandro


g++是错误的,clang是正确的,在模板template中的名称也是可选的。 - aaronman
2个回答

9
我认为Clang是正确的,而g++是错误的,引用自标准草案(粗体强调是我的)。
14.6.1 局部声明的名称 [temp.local]
与普通(非模板)类一样,类模板具有一个注入的类名(第9条)。注入的类名可以用作模板名或类型名。当它与模板参数列表一起用作模板模板参数,或者作为友元类模板声明的 elaborated-typespecifier 中的最后一个标识符时,它引用类模板本身。否则,它等效于跟随在<>中的类模板的模板参数的模板名称。
您可以使用::作用域解析运算符来打败g++。
template <typename T> 
struct C2
{
  template <typename Type = int,
        template <typename Ti> class Container = ::C2> 
                                              // ^^ <-- here is the solution!
  void m() {}

};

Live Example.


@Irleon 很高兴能够帮到您。欢迎来到 Stackoverflow! - TemplateRex
1
@TemplateRex,我希望Irleon或者你已经检查过GCC是否有关于这个问题的错误报告,或者已经创建了一个?虽然SO很好,但它不能解决问题。我通常会链接到bugzilla让人们知道,以便他们可以稍后检查哪个版本已经修复了这个问题。(另外:+1) - Daniel Frey
@DanielFrey 我有点时间紧迫,而且这个问题有一个相当简单的解决方法,所以它可能不会得到高优先级。也许原帖的作者可以提交一个解决方案?顺便说一句,我今天回答了另一个可能是bug的问题,很高兴知道我也解决了那个问题。 - TemplateRex
1
@TemplateRex 我已经将其报告为[bugzilla#58538](http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58538),让我们看看GCC的人如何反应。根据我的经验,他们通常会查看它,思考一下,如果解决方案是在其代码库中的某个小型本地化修复,则非常快速。我确实想知道使用`C2`作为默认值是否很重要-有时默认模板(template)参数的规则是不同的。嗯... - Daniel Frey
@DanielFrey 感谢您的错误报告。值得一提的是:在您的错误报告中,将 void f(); 替换为 class Inner; 会产生相同的错误消息,因此这与 C++11 中针对 函数 模板默认模板参数的限制解除无关。 - TemplateRex

0

那么TemplateRex答案中的14.6.1参考是否意味着G++是正确的(而Clang和VC++是错误的),因为它将X用作模板模板参数的模板参数?

template< template< typename > class T >
class factory { };

template< typename T >
class X
{
      friend class factory< X >;  // ***
};

int main()
{
}

在这个例子中,G++将X作为类模板的名称处理,而Clang和VC++将其视为注入类名。
编辑:Clang 5.0.0现在接受该代码,与G++和EDG相同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接