2013-05-01 59 views
2

我试图获得T2<B>模板别名从C的一个实例化名模板

template<typename A> 
struct T1 
{ 
    template<typename B> 
    struct T2{}; 
}; 

template<typename A> 
class C 
{ 
    T1<A> t; 
}; 

template<typename A> 
using U1=decltype(C<A>::t); 

template<typename A, typename B> 
using U2=typename U1<A>::T2<B>; 

我得到一个编译失败用gcc 4.8开始:

gg.cc:18:28: error: expected ‘;’ before ‘<’ token 
using U2=typename U1<A>::T2<B>; 

我有在每个明智的位置使用了typename关键字,但无法获取U2定义进行编译。

这里的正确语法是什么?如果我可以在不借助U1的情况下得到U2的定义,那将会更好。

回答

4

您需要使用template消歧告诉编译器解析T2为模板的名称(以及随后的<>作为相应的模板参数的分隔符):

template<typename A, typename B> 
    using U2=typename U1<A>::template T2<B>; 
//       ^^^^^^^^ 

这里是一个编译live example

Here你可以找到时,你应该使用template消歧的一些详细信息(和typename消歧为好,虽然你似乎是知道的那一个)。

+0

我以前只在成员模板函数中看到过这个。谢谢,我从来没有发现过我自己的。 – mirk 2013-05-01 10:13:41

+0

@mirk:很高兴帮助。我在SO上添加了一个有用的Q&A的链接,详细解释如下。 – 2013-05-01 10:15:30

1

当编译器编译如下:

template<typename A, typename B> 
using U2=typename U1<A>::T2<B>; 

读取嵌套名指定U1<A>::后,不知道它是其中的U1专业化,因为A是未知的。每个U1 specializitonon可以完全不同,并取决于什么A是。所以它不知道什么样的名字T1是。特别是它不知道它是否是模板名称。 (例如U1<int>::T1可能是什么U1<char>::T1是完全不同的。)

出于这个原因,你需要明确地告诉T1会通过T1之前使用template关键字是一个模板名称,编译器。