Recursively nested templates - gcc error?

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 without warning about GCC 4.4.5, as well as MSVC 2010, but not in 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, although I do not see anything non-standard in this question, the question is mandatory - is this legal in C ++? Also, if so, how do I submit a bug report to GCC? (

to change . A small background for the curious:

This is supposed to be a metaprogramming pattern. f basically has a template metaclass class structure with apply replaced by a (of course, the nested type of apply omitted, so we can focus on the structure itself).

Inheritance in this case is the standard device for binding metafile return values. What this piece is trying to achieve is a class of metaphors that recursively gives itself when evaluating.

edit2 : let me put the same fragment in a different way:

 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 leads to the same error. I think this refutes the argument of an incomplete type.

+6
source share
4 answers

There were some good notes in the existing answers. First, the type f is incomplete during the definition of the nested class template, but f is the dependent type. Now, if you create an instance of the nesting template ( f ), it creates an instance of the declaration of the nested template (member). Note that a member declaration does not include a list of basic sentences, so it does not need full base classes. After the nesting pattern was created implicitly, f complete, and when it comes to instantiating the member definition, there should be no more problems. So I don’t think it’s more correct to complain here.

Another mistake is that f<int>::a<int>::a actually calls the constructor a<int> and requires it to be a constructor template (with <int> being the template argument). The basis of this was DR # 147 .

Conversion to the constructor is not performed when the classifier name is not a class of the name of the entered class. For example, if it is a derived class, your code becomes valid (as it turned out in some answers).

+4
source

Good question. This seems to be a problem with gcc for a recursive template declaration. Because, if there were solid classes, then it would throw an error, and ideally it should be declared as:

 struct Out { struct In; }; struct Out::In : Out {}; 
+2
source

it looks like GCC 4.5 thinks you specified the constructor.

one possible workaround:

 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; } 
+1
source

Using Como on the Internet, he suggests that f is an incomplete type at the point where you use it as a base class, and as such is not suitable.

 "ComeauTest.c", line 5: error: incomplete type is not allowed struct a : f 

Unfortunately, I do not have a clang instance.

0
source

Source: https://habr.com/ru/post/887070/


All Articles