-
January 5th, 2009, 12:07 AM
#1
self-referencing policies
Hello,
I've just discovered policy based design (due to a forum topic a few days ago) and am having fun playing around with it. Here's a little question I ran into: I want my policy class to have a convenient label for the datatype inherent to its derived class. Here's my bare-bones example:
Code:
template<class T>
class policy{
public:
typedef typename T::fooType fooType;
};
template<class fooType>
class foo : public policy<foo<fooType> >{
};
int main(){
foo<int> F;
return 0;
}
This doesn't compile (gcc v4.1), because at the time the typedef is evaluated by the compiler, foo is not yet fully defined. Any ideas how to get around this? I know I could nix the typedef and use T::fooType explicitly, but that gets very messy in my "real world" example...
-
January 5th, 2009, 04:07 AM
#2
Re: self-referencing policies
I think forward declaration may off the compile error.
Thanks for your help.
-
January 5th, 2009, 05:21 AM
#3
Re: self-referencing policies
Did you expect it to compile?
The compiler is looking for int::fooType and theres no such animal.
Get Microsoft Visual C++ Express here or CodeBlocks here.
Get STLFilt here to radically improve error messages when using the STL.
Get these two can't live without C++ libraries, BOOST here and Loki here.
Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
Always use [code] code tags [/code] to make code legible and preserve indentation.
Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.
-
January 5th, 2009, 09:49 AM
#4
Re: self-referencing policies
okay, how about this variation? I still get an error on compilation. I tried various combinations of predeclaring each class, but they don't seem to do the trick.
Code:
template<class T>
class policy{
public:
typedef typename T::fooType fooType;
};
template<class T>
class foo : public policy<foo<T> >{
typedef T fooType;
};
int main(){
foo<int> F;
return 0;
}
-
January 5th, 2009, 09:55 AM
#5
Re: self-referencing policies
Read Russco's comment again.
-
January 5th, 2009, 10:15 AM
#6
Re: self-referencing policies
Originally Posted by jakevdp
okay, how about this variation? I still get an error on compilation. I tried various combinations of predeclaring each class, but they don't seem to do the trick.
Code:
template<class T>
class policy{
public:
typedef typename T::fooType fooType;
};
template<class T>
class foo : public policy<foo<T> >{
typedef T fooType;
};
int main(){
foo<int> F;
return 0;
}
This still doesn't make any sense. In order for the policy class to resolve T::fooType, T needs to be a complete type, which it can't be because at this point in the instantiation we're still evaluating its base class. This is the stuff "internal compiler error"s are made of.
Why not just do the following:
Code:
template<class T>
class policy{
public:
typedef T fooType;
};
template<class T>
class foo : public policy<T>{
};
int main(){
foo<int> F;
return 0;
}
?
- Alon
-
January 5th, 2009, 12:22 PM
#7
Re: self-referencing policies
okay, how about this variation? I still get an error on compilation. I tried various combinations of predeclaring each class, but they don't seem to do the trick.
Aside from what they've pointed out about why the typedef won't work, what you're trying to do here is just odd. Using a derived class as the template parameter for its own base class?
-
January 5th, 2009, 12:27 PM
#8
Re: self-referencing policies
Originally Posted by Speedo
what you're trying to do here is just odd. Using a derived class as the template parameter for its own base class?
It is odd indeed. Read up on the "curiously recurring template pattern".
-
January 5th, 2009, 01:47 PM
#9
Re: self-referencing policies
Hello,
I found a solution - I thought I'd share it with you. This was pointed out to me by a friend, and comes from the FLENS source code (see http://flens.sourceforge.net/ ). This compiles, and creates the behavior I hoped for:
Code:
template <typename T>
struct TypeInfo;
template<class T>
class policy{
public:
typedef typename TypeInfo<T>::Type DerivedType;
};
template<class T>
class foo : public policy<foo<T> >{};
template <typename T>
struct TypeInfo<foo<T> >
{
typedef foo<T> Type;
};
int main(){
foo<int> F;
policy<foo<int> >& P = F; // F::DerivedType is foo<int>
return 0;
}
Essentially, policy:: DerivedType is shorthand for the class that derives from it, as long as that derived type defines a TypeInfo specialization for itself. Kind of a cool trick, and useful, for returning data from a base class which is of the derived class type. This simplifies my code, anyway. Any remarks on this type of structure?
-
January 5th, 2009, 01:56 PM
#10
Re: self-referencing policies
Originally Posted by jakevdp
Hello,
I found a solution -
Sounds exactly like what Peter_APIT suggested in the very first reply to your question.....a simple forward declaration of...
Code:
template <typename T>
struct TypeInfo;
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 5th, 2009, 02:15 PM
#11
Re: self-referencing policies
Originally Posted by TheCPUWizard
Sounds exactly like what Peter_APIT suggested in the very first reply to your question.....a simple forward declaration of...
While a forward declaration may be necessary, I see that the solution found by jakevdp is substantially different from the code originally posted. The typedef was the problem then and that was addressed by Russco when he said int::fooType is not valid. It now appears to me that the original was just a very bad attempt at implementing the "curiously recurring template pattern" (as pointed out by laserlight) which has now been corrected. Is my analysis wrong?
-
January 5th, 2009, 02:19 PM
#12
Re: self-referencing policies
Hang on, that doesn't do what the original post was trying to achieve. In the OP, you had policy defining a type declared within the template argument
Code:
template<class T>
struct policy
{
typedef typename T::fooType fooType;
};
The one you've just posted is functionally equivalent to
Code:
template<class T>
struct policy
{
typedef T DerivedType;
};
(or has the cold addled my brain, and I'm missing something obvious?)
ETA: I see someone else has had the same thought - maybe it's not just me, then.
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
January 5th, 2009, 03:52 PM
#13
Re: self-referencing policies
Right - thanks. The original example was trying for something like this:
Code:
template <typename T>
struct TypeInfo;
template<class T>
class policy{
public:
typedef typename TypeInfo<T>::Type DerivedType;
};
template<class T>
class foo : public policy<foo<T> >{};
template <typename T>
struct TypeInfo<foo<T> >
{
typedef T Type;
};
int main(){
foo<int> F;
policy<foo<int> >& P = F; // P::DerivedType is int
return 0;
}
Using this, a policy object can know about any of the template parameters of a derived type. That's what I was going for.
Last edited by jakevdp; January 5th, 2009 at 03:57 PM.
Reason: typo
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|