curiously recurring template pattern problem

D

Denis Remezov

John said:
[snip]

Secondly is there a way to achieve what I want, which is to let X know the
definition of a type defined in any class derived from X, by passing the
derived type as a template parameter to X (aka the curiously recurring
template pattern).

Thanks,
john


How about this:

template <class DerivedTraits, class Derived>
struct X
{
// typedef typename Derived::type type;
typedef typename DerivedTraits::type type;
};

struct YTraits {
typedef int type;
};

struct Y : public YTraits, X<YTraits, Y>
{
// typedef int type;
};


Denis
 
D

Denis Remezov

Denis said:
John said:
[snip]

Secondly is there a way to achieve what I want, which is to let X know the
definition of a type defined in any class derived from X, by passing the
derived type as a template parameter to X (aka the curiously recurring
template pattern).

Thanks,
john

How about this:

template <class DerivedTraits, class Derived>
struct X
{
// typedef typename Derived::type type;
typedef typename DerivedTraits::type type;
};

struct YTraits {
typedef int type;
};

struct Y : public YTraits, X<YTraits, Y>
{
// typedef int type;
};

Denis

In other words, I meant refactoring the derived class into two parts, the
first of which does not depend on X, then using it as above. Doing so breaks
the circular dependence of the original scheme, in which X gets parsed first,
attempting to look up names to be declared in Y, which hasn't been parsed
yet because it has X as a base. A bit of a prop to the compiler here.

Denis
 
J

John Harrison

The following code does not compile

template <class Derived>
struct X
{
typedef typename Derived::type type;
};

struct Y : public X<Y>
{
typedef int type;
};

int main()
{
}

gcc and VC++ 7 give unhelpful error messages but Comeau C++ says 'incomplete
type is not allowed' pointing at the typedef in X.

Can someone explain to my why this should be a problem? I'm presuming that
this kind of construct is difficult or impossible to compile for some
reason.

Secondly is there a way to achieve what I want, which is to let X know the
definition of a type defined in any class derived from X, by passing the
derived type as a template parameter to X (aka the curiously recurring
template pattern).

Thanks,
john
 
C

Chris Theis

John Harrison said:
The following code does not compile

template <class Derived>
struct X
{
typedef typename Derived::type type;
};

struct Y : public X<Y>
{
typedef int type;
};

int main()
{
}

gcc and VC++ 7 give unhelpful error messages but Comeau C++ says 'incomplete
type is not allowed' pointing at the typedef in X.

Hi John,

Interesting thing - to me it seems that this is a problem regarding the
order of how and when the template parameters are substituted and when
typedefs are resolved. However, I´m not an expert on compiler techniques so
I´d also be interested if somebody could shed some more light onto this,
please.
Can someone explain to my why this should be a problem? I'm presuming that
this kind of construct is difficult or impossible to compile for some
reason.
[SNIP]

There is a way to circumvent this (IMHO probably correct behavior) by using
templates only instead of typedefs.

template <class Derived, typename DerivedType>
struct X
{
X() {};
~X() {};
void test() { cout << typeid( type ).name() << endl; };
typedef typename DerivedType type;
};

template<typename InternalType>
struct Y : public X<Y, InternalType>
{
Y() {};
~Y() {};
};

int main()
{
Y<int> MyObj;
MyObj.test();
return 1;
}

HTH
Chris
 
R

Rolf Magnus

John said:
The following code does not compile

template <class Derived>
struct X
{
typedef typename Derived::type type;
};

struct Y : public X<Y>

At this point, Y is incomplete, but X must be instantiated based on Y.
The compiler doesn't yet know Y::type. At least that's how I think it
works. I don't know a solution to your problem.
 
S

Sharad Kala

Chris Theis said:
John Harrison said:
The following code does not compile
[SNIP]

There is a way to circumvent this (IMHO probably correct behavior) by using
templates only instead of typedefs.

template <class Derived, typename DerivedType>
struct X
{
X() {};
~X() {};
void test() { cout << typeid( type ).name() << endl; };
typedef typename DerivedType type;

I don't think you need a typename here.
};

template<typename InternalType>
struct Y : public X<Y, InternalType>

Isn't Y a class template? In that case writing public X<Y, InternalType> should
be an error.

-Sharad
 
S

Sharad Kala

John Harrison said:
The following code does not compile
\> Can someone explain to my why this should be a problem? I'm presuming that
this kind of construct is difficult or impossible to compile for some
reason.

In CRTP even though the base class depends on the derived class, it cannot do so
in a way that requires the complete type of derived to be known to the base
class.

-Sharad
 
T

tom_usenet

Secondly is there a way to achieve what I want, which is to let X know the
definition of a type defined in any class derived from X, by passing the
derived type as a template parameter to X (aka the curiously recurring
template pattern).

This might help:

template <class Derived, class T>
struct X
{
typedef T type;
};

struct Y : public X<Y, int>
{
};

int main()
{
}

At what point does X need to know the type of "type" though? If it
isn't required by the definition of X, but only the definition of its
members, then you shouldn't have a problem. e.g.

template <class Derived>
struct X
{
void foo()
{
typedef typename Derived::type type;
//use type
}
};

struct Y : public X<Y>
{
typedef int type;
};


Tom
 

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

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top