6

When tryin to compile this (CRTP-like) code with GCC 4.6.0:

template<template<class> class T> struct A;

template<class T> 
struct B: A<B<T>::template X> {
    template <class U> struct X { U mem; };
};

B<int> a;

I get the errormessage "test.cpp:3:26: error: no class template named ‘X’ in ‘struct B<int>’". Why does X seem to be invisible outside the class definition?

Tom De Caluwé
  • 926
  • 5
  • 17
  • My compiler has a problem with this: : A< B::template X> The X is an undeclared identifier. I'm frankly confused by your syntax, what's B::template supposed to be? Besides I've never seen: template class T. If anything, I think I'm going to learn something from you; can you please explain the importance of the syntax, what these do? – leetNightshade Apr 26 '11 at 18:01
  • I'm not sure, but maybe Johannes's answer from this topic might help here : http://stackoverflow.com/questions/4420828/another-bug-in-g-clang-c-templates-are-fun – Nawaz Apr 26 '11 at 18:04
  • @leetNightshade: I'm not sure but I think you're error message is actually saying the same thing as mine: that X is not visible outside B (this is how I understand it anyway). About your second question: "template class T" means that T is templated itself. Like that you can use something like T inside the class definition of A. – Tom De Caluwé Apr 26 '11 at 18:07
  • 1
    What are you trying to do...? – Andrew Rasmussen Apr 26 '11 at 18:09

3 Answers3

4

As Emile Cormier correctly points out here the problem is that at the place of instantiation of A, B is still an incomplete type, and you cannot use the inner template.

The solution for that is moving the template X outside of the template B. If it is independent of the particular instantiation T of the template B, just move it to the namespace level, if it is dependent on the instantiation, you can use type traits:

template <typename T>
struct inner_template 
{
   template <typename U> class tmpl { U mem; }; // can specialize for particular T's
};
template <typename T>
struct B : A< inner_template<T>::template tmpl >
{
};
Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2

struct B is still considered an incomplete type when you specify A<B<T>::template X> as the base class.

Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
1

You're trying to use a member of B as a parent of B creating a recursive-esque situation. For example this doesn't compile either:

template<template<class> class T> struct A {};

struct B : public A<B::nested>
{
        struct nested {};
};
Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 1
    That's not true: I'm passing B as a template parameter, I'm not inheriting from it. – Tom De Caluwé Apr 26 '11 at 18:13
  • @Tom De Caluwé I changed my answer to show that even as a template parameter it's still treated as an incomplete type which can't be used as a template parameter. – Mark B Apr 26 '11 at 18:18