MoreCRTP question

K

kostas

Hi all
I encountered a problem testing a variation of CRTP.
(It's also proposed in "C++ Templates: The Complete Guide" by
Vandevoorde, Josuttis. See the MoreCurious template class in 16.3)

template<class T, template <typename> class D>
class Base
{
protected:
Base(T x): i(x) {}

T i;
};

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, Derived>(x){}
};

the problem is that in the Base ctor call (from within Derived ctor)
the Derived parameter is not recognized as class template. Old gcc
versions(3.3.3) could cope with this, but not any more. Other
compilers have also problem.

So is it a language or a compiler issue?
Do you know some workaround?
Any help is appreciated.

Kostas
 
I

Ian Collins

kostas said:
Hi all
I encountered a problem testing a variation of CRTP.
(It's also proposed in "C++ Templates: The Complete Guide" by
Vandevoorde, Josuttis. See the MoreCurious template class in 16.3)

template<class T, template <typename> class D>
class Base
{
protected:
Base(T x): i(x) {}

T i;
};

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, Derived>(x){}
};

the problem is that in the Base ctor call (from within Derived ctor)
the Derived parameter is not recognized as class template. Old gcc
versions(3.3.3) could cope with this, but not any more. Other
compilers have also problem.

So is it a language or a compiler issue?

It looks OK to me and Sun CC accepts it.
 
A

Alf P. Steinbach

* kostas:
Hi all
I encountered a problem testing a variation of CRTP.
(It's also proposed in "C++ Templates: The Complete Guide" by
Vandevoorde, Josuttis. See the MoreCurious template class in 16.3)

template<class T, template <typename> class D>
class Base
{
protected:
Base(T x): i(x) {}

T i;
};

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, Derived>(x){}
};

the problem is that in the Base ctor call (from within Derived ctor)
the Derived parameter is not recognized as class template. Old gcc
versions(3.3.3) could cope with this, but not any more. Other
compilers have also problem.

So is it a language or a compiler issue?
Do you know some workaround?
Any help is appreciated.

I failed to find anything about it in the standard, but adding the magic
word "class" before "Derived" seems to do the trick.
 
K

kostas

I failed to find anything about it in the standard, but adding the magic
word "class" before "Derived" seems to do the trick.

if you mean this:
template<class T>
class Derived:public Base<T, Derived>
{
public:
Derived(T x):Base<T, class Derived>(x){}

};

it doesn't work for me(gcc 3.4.4 or 4.1.1)
what compiler do you use?
 
A

Alf P. Steinbach

* kostas:
if you mean this:
template<class T>
class Derived:public Base<T, Derived>
{
public:
Derived(T x):Base<T, class Derived>(x){}

};

it doesn't work for me(gcc 3.4.4 or 4.1.1)
what compiler do you use?

MSVC 7.1, but now that I checked it with Comeau Online it's evidently an
MS extension, not kosher, so no wonder I didn't find it in the standard.

I don't see any solution to the technical problem, how to refer to
Derived as a general non-specialized template within the Derived class.

However, it shouldn't be difficult to create a workaround at the design
level. E.g., simply move whatever functionality that Base uses in
Derived, to some other class, e.g. another base class of Derived. Or
perhaps you don't really need a template template parameter, perhaps all
that's needed is an ordinary type parameter.
 
K

kostas

However, it shouldn't be difficult to create a workaround at the design
level
Thanks for the response, but i wish i could use this design.
After all it's only a slight variation of a well known pattern.
 
I

Ian Collins

Alf said:
* kostas:



MSVC 7.1, but now that I checked it with Comeau Online it's evidently an
MS extension, not kosher, so no wonder I didn't find it in the standard.
Did Comeau Online complain about the original?
 
I

Ian Collins

Ian said:
Did Comeau Online complain about the original?
OK, I realise why the original should not compile now. I've used this
construct before with Sun CC, so I guess it's a compiler bug that lets
it compile!
 
Z

Zeppe

kostas said:
Hi all
Hi!


template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, Derived>(x){}
};

the problem is that in the Base ctor call (from within Derived ctor)
the Derived parameter is not recognized as class template. Old gcc
versions(3.3.3) could cope with this, but not any more. Other
compilers have also problem.

So is it a language or a compiler issue?

I think it's a language issue, even if I haven't read carefully the
standard to prove it :)
Do you know some workaround?

What do you think about:

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, ::Derived>(x){}
};

In this way according to me you are explicitly referring to the template
class and not the specific specialization Derived<T>.

Regards,

Zeppe
 
K

kostas

What do you think about:

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, ::Derived>(x){}

};

In this way according to me you are explicitly referring to the template
class and not the specific specialization Derived<T>.

Thanks a lot. It works.
I think it also makes sense. So I hope it's not just another magic.
 
I

Ian Collins

Zeppe said:
What do you think about:

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, ::Derived>(x){}
};

In this way according to me you are explicitly referring to the template
class and not the specific specialization Derived<T>.
Nice one!
 
V

vandevoorde

Hi all
I encountered a problem testing a variation of CRTP.
(It's also proposed in "C++ Templates: The Complete Guide" byVandevoorde, Josuttis. See the MoreCurious template class in 16.3)

template<class T, template <typename> class D>
class Base
{
protected:
Base(T x): i(x) {}

T i;

};

template<class T>
class Derived:public Base<T, Derived>
{
Derived(T x):Base<T, Derived>(x){}

};

the problem is that in the Base ctor call (from within Derived ctor)
the Derived parameter is not recognized as class template. Old gcc
versions(3.3.3) could cope with this, but not any more. Other
compilers have also problem.

So is it a language or a compiler issue?

It's a language issue: Using the unqualified name "Derived" finds the
injected class name, which can only be used to denote a type name (not
a bare template name; although you can append the template arguments).
Do you know some workaround?


Yes, use a qualified name. In your example, use "::Derived", as in:

Derived(T x):Base<T, ::Derived>(x){}

I hope that helps,

Daveed
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top