递归嵌套模板——gcc bug?
我有以下片段。
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
(当然,省略了 apply
的嵌套 type
,这样我们就可以专注于结构本身)
。在本例中,这是一个用于绑定元函数返回值的标准设备。这个片段试图实现的是一个元函数类,它在评估时会递归地产生自身:
让我以不同的方式放置相同的片段:
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;
}
我认为这会产生相同的错误,它驳斥了不完整的类型参数。
I have the following snippet.
template< typename T >
struct f
{
template< typename V >
struct a : f
{};
};
int main ()
{
f<int>::a<int>::a<double> x;
}
It compiles with no warnings on GCC 4.4.5 and also MSVC 2010, but not on GCC 4.5.2 -- on which I get the following errors:
test.cc: In function 'int main()':
test.cc:11:21: error: expected primary-expression before 'double'
test.cc:11:21: error: expected ';' before 'double'
So while I don't see anything non-standard about it, the question is obligatory -- is this legal in C++? Also, if it is, how do I file a bug report at GCC? (:
edit: A little background for the curious:
This is supposed to be a piece of template metaprogramming. f
basically has the structure of a template metafunction class with apply
substituted for a
(of course the nested type
of apply
is omitted so we can concentrate on the structure itself).
Inheritance in this case is a standard device for binding metafunction return values. What this snippet is trying to achieve is a metafunction class that recursively yields itself when evaluated.
edit2: let me put the same snippet a bit differently:
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;
}
This produces the same error. I think it refutes the incomplete type argument.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
现有答案中有一些很好的注释。首先,
f
的类型在定义嵌套类模板时是不完整的,但f
是一个依赖类型。现在,如果您实例化嵌套模板 (f
),它将实例化嵌套模板(成员)的声明。请注意,成员的声明不包括基本子句列表,因此不需要完整的基类。一旦嵌套模板被隐式实例化,f
就完成了,当涉及到实例化成员的定义时,应该不再有问题了。所以我认为科莫在这里抱怨是不正确的。另一个错误是,实际上
f::a::a
正在命名a
的构造函数,并要求它是构造函数模板(
是模板参数)。其基础是DR #147。当限定符名称不是注入类名的类时,不会完成对构造函数的转换。例如,如果它是派生类,您的代码将变得有效(正如一些答案所得出的那样)。
There were a couple of good notes in existing answers. First,
f
's type is incomplete at the time the nested class template is defined, butf
is a dependent type. Now, if you instantiate the nesting template (f
), it will instantiate a declaration of the nested template (the member). Note that the declaration of the member does not include the base clause list, so it doesn't need complete base classes. Once the nesting template has been instantiated implicitly,f
is complete and when it comes to instantiating the definition of the member, there should be no issue anymore. So I don't think that comeau is correct complaining here.The other bug is that, in fact,
f<int>::a<int>::a
is naming the constructor ofa<int>
, and requires it to be a constructor template (with<int>
being the template arguments). The base of this was DR #147.The translation to the constructor is not done when the qualifier name isn't the class of the injected class name. For example, if it is a derived class, your code becomes valid (as some answers figured out).
好问题。这似乎是
gcc
的template
递归声明的问题。因为,如果存在实体类,那么它会给出错误,理想情况下应该将其声明为:Nice question. This seems to be an issue with
gcc
fortemplate
recursive declaration. Because, had there been solid classes then it gives error and ideally it should be declared as:看起来 GCC 4.5 认为您已经指定了构造函数。
一种可能的解决方法:
it looks like GCC 4.5 believes you have specified the constructor.
one possible workaround:
在线使用 Comeau,它表明当您将
f
用作基类时,它是一个不完整的类型,因此是不合适的。不幸的是,我手头没有 clang 实例。
Using Comeau online, it suggests that
f
is an incomplete type at the point you use it as a base class, and as such is unsuitable.I don't have a clang instance at hand unfortunately.