I want to derive a type Test
from a templated type Base
which I specialise on the derived type (i.e. Base<Test>
).
Inside the templated type, I want to make use of a typedef defined in the derived type (the template parameter).
However, I get this compile error:
error C2039: 'X' : is not a member of 'Test'
Here is the code snippet:
template <typename T>
class Base
{
protected:
void func(typename T::X x) {}
};
class Test : public Base<Test>
{
public:
typedef int X;
};
Is this doable, and if so, what is the fix I need to make?
(I see a couple of answers for this kind of problem but it looks like my scenario isn't fixed by prefixing typename - is it something to do with deriving from a template specialised with the derived type?)
Alternatively to the typedef, you can also declare the type as second template argument in the base class:
template <typename T, typename X>
class Base
{
protected:
void func(X x) {}
};
class Test : public Base<Test, int>
{
public:
// typedef int X;
};
This works for me:
template <typename T> struct Traits;
template <typename Derived>
class Base
{
protected:
void func(typename Traits<Derived>::X x) {}
};
class Test;
template <> struct Traits<Test>
{
typedef int X;
};
class Test : public Base<Test>
{
};
I'm not sure about this behavior, maybe someone can clarify it. But as I understand by the moment you do : public Base<Test>
the type name X doesn't exists (since is declared below).
If you create a wrapper class before making the inheritance the type would exists by the moment you do the inheritance and the template instantiation will work.
This compiles with VC++ 2013
template <typename T>
class Base
{
protected:
void func(typename T::X x) {}
};
class TestWrapper
{
public:
typedef int X; //Declared, now it exists for the compiler
};
class Test
:public Base<TestWrapper> //Compiles correctly
{
};
You have a circularity which cannot be resolved with forward declarations. But this will work, although (I suspect) not quite so strongly defined as you wanted.
template <typename T>
class Base
{
protected:
template<typename Y>
void func(Y x) {}
};
class Test : public Base<Test>
{
public:
typedef int X;
};
If func
were public, then you could then write
Test t;
Test::X x;
t.func(x)
which is satisfactory for any use of the Curiously Recurring Template Pattern I think of.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With