473,591 Members | 2,926 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

curiously recurring template pattern problem

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
Jul 22 '05 #1
14 2571
John Harrison wrote:
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.
{
typedef int type;
};

int main()
{
}


Jul 22 '05 #2
John Harrison wrote:
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.
{
typedef int type;
};

int main()
{
}


Jul 22 '05 #3
John Harrison wrote:
[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
Jul 22 '05 #4
John Harrison wrote:
[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
Jul 22 '05 #5
"John Harrison" <jo************ *@hotmail.com> wrote in message
news:c5******** *****@ID-196037.news.uni-berlin.de...
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<typena me InternalType>
struct Y : public X<Y, InternalType>
{
Y() {};
~Y() {};
};

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

HTH
Chris
Jul 22 '05 #6
"John Harrison" <jo************ *@hotmail.com> wrote in message
news:c5******** *****@ID-196037.news.uni-berlin.de...
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<typena me InternalType>
struct Y : public X<Y, InternalType>
{
Y() {};
~Y() {};
};

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

HTH
Chris
Jul 22 '05 #7
Denis Remezov wrote:

John Harrison wrote:

[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
Jul 22 '05 #8
Denis Remezov wrote:

John Harrison wrote:

[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
Jul 22 '05 #9

"Chris Theis" <Ch************ *@nospam.cern.c h> wrote in message
news:c5******** **@sunnews.cern .ch...
"John Harrison" <jo************ *@hotmail.com> wrote in message
news:c5******** *****@ID-196037.news.uni-berlin.de...
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<typena me 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
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
2246
by: papi1976 | last post by:
Hello to everyone I heard about a strange thing about wich i have'nt find anything on the net or books, someone called this "Curiously recursive pattern" or a strange trick to play with templates and inheritance... Dunno what is that or how it works :( Does someone has any idea about this thing???
14
521
by: John Harrison | last post by:
The following code does not compile template <class Derived> struct X { typedef typename Derived::type type; }; struct Y : public X<Y> {
15
3074
by: iuweriur | last post by:
A few questions on the curiously recurring template pattern: This page: http://c2.com/cgi/wiki?CuriouslyRecurringTemplate this part: template<typename T> struct ArithmeticType { T operator + (const T& other) const {
4
1487
by: Martin MacRobert | last post by:
Hi Gang, The following code does not compile, but I can't figure out why. The compiler complains that the CuriouslyDerivedType (CRDerived) does not publish the "value_type", yet in fact the class CRDerived does. Is there any way of making the code work? I would like functions to accept a CRBase template, and the CRBase must be able to deduce the "value_type" of the function that it is "curiously calling". Thanks.
4
3089
by: chsalvia | last post by:
The "Curiously Recurring Template Pattern" (CRTP) recently caught my attention as a nice trick which allows static polymorphism. In other words, it lets you build extensible classes without the overhead of virtual function calls. (But of course, with the limitation of compile-time resolving.) Basically, you create a templated Base Class which defines an interface function that uses a static_cast to call a member function in Derived. ...
0
7934
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8236
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8362
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
7992
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8225
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
5732
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
1
2378
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1465
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1199
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.