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 14 2542
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() { }
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() { }
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
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
"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<typename InternalType>
struct Y : public X<Y, InternalType>
{
Y() {};
~Y() {};
};
int main()
{
Y<int> MyObj;
MyObj.test();
return 1;
}
HTH
Chris
"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<typename InternalType>
struct Y : public X<Y, InternalType>
{
Y() {};
~Y() {};
};
int main()
{
Y<int> MyObj;
MyObj.test();
return 1;
}
HTH
Chris
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
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
"Chris Theis" <Ch*************@nospam.cern.ch> 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<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
"Chris Theis" <Ch*************@nospam.cern.ch> 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<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
"John Harrison" <jo*************@hotmail.com> wrote in message
news:c5*************@ID-196037.news.uni-berlin.de... 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
"John Harrison" <jo*************@hotmail.com> wrote in message
news:c5*************@ID-196037.news.uni-berlin.de... 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
On Wed, 7 Apr 2004 08:12:59 +0100, "John Harrison"
<jo*************@hotmail.com> wrote: 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
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
On Wed, 7 Apr 2004 08:12:59 +0100, "John Harrison"
<jo*************@hotmail.com> wrote: 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
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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>
{
|
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...
|
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...
|
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...
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
| |