我有以下代码段。
template< typename T >
struct f
{
template< typename V >
struct a : f
{};
};
int main ()
{
f<int>::a<int>::a<double> x;
}
它在GCC 4.4.5和MSVC 2010上没有警告编译,但在GCC 4.5.2上没有 - 我得到以下错误:
test.cc: In function 'int main()':
test.cc:11:21: error: expected primary-expression before 'double'
test.cc:11:21: error: expected ';' before 'double'
所以虽然我没有看到任何关于它的非标准,但问题是强制性的 - 这在C ++中是合法的吗?此外,如果是,我如何在GCC提交错误报告? (:
编辑:好奇的一点背景:
这应该是一个模板元编程。 f
基本上具有模板元函数类的结构,其中apply
替换为a
(当然,type
的嵌套apply
被省略,因此我们可以专注于结构本身)。
在这种情况下,继承是用于绑定元函数返回值的标准设备。这个代码片段试图实现的是一个元函数类,它在评估时以递归方式自我产生。
edit2 :让我对相同的代码段略有不同:
template< typename T >
struct f
{
template< typename V > struct a;
};
template< typename T >
template< typename V >
struct f<T>::a : f<T>
{};
int main ()
{
f<int>::a<int>::a<double> x;
}
这会产生相同的错误。我认为它驳斥了不完整的类型参数。
答案 0 :(得分:4)
现有答案中有几个好的笔记。首先,f
的类型在定义嵌套类模板时是不完整的,但f
是依赖类型。现在,如果您实例化嵌套模板(f
),它将实例化嵌套模板(成员)的声明。请注意,成员的声明不包括基本子句列表,因此它不需要完整的基类。一旦嵌套模板被隐式实例化,f
就完成了,当涉及实例化成员的定义时,应该没有问题了。所以我不认为这里的抱怨是正确的抱怨。
另一个错误是,事实上,f<int>::a<int>::a
正在命名a<int>
的构造函数,并要求它是一个构造函数模板(<int>
是模板参数)。其基础是DR #147。
当限定符名称不是注入的类名的类时,不会转换到构造函数。例如,如果它是派生类,则代码变为有效(如某些答案所示)。
答案 1 :(得分:2)
好问题。这似乎是gcc
template
递归声明的问题。因为,如果有固体类,那么它会给出错误,理想情况下它应该声明为:
struct Out {
struct In;
};
struct Out::In : Out {};
答案 2 :(得分:1)
看起来GCC 4.5认为你已经指定了构造函数。
一种可能的解决方法:
template<typename T>
struct f {
template<typename V>
struct a : f {
template<typename Z>
struct q {
typedef a<Z> Q;
};
};
};
int main() {
f<int>::a<int>::q<double>::Q x;
return 0;
}
答案 3 :(得分:0)
在线使用Comeau,它表明f
在您将其用作基类时是不完整的类型,因此不适合。
"ComeauTest.c", line 5: error: incomplete type is not allowed
struct a : f
不幸的是,我手头没有clang实例。