Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > User defined class meta data (type traits?)

Reply
Thread Tools

User defined class meta data (type traits?)

 
 
greek_bill
Guest
Posts: n/a
 
      10-29-2008
Hi,

I'm trying to develop a system where I can register some data/
information about a class. For example

// ClassInfo.h
template <class T>
struct ClassInfo
{
static const std::string tagName;
static const int version;
static const bool isConfigurable;
};

// FooBar.h
class FooBar {...};

// FooBar.cpp
template<> const std::string ClassInfo<FooBar>::tagName = "FooBar";
template<> const int ClassInfo<FooBar>::version = 1;
template<> const bool ClassInfo<FooBar>::isConfigurable = false;

// main.cpp
....
#include "FooBar.h"
if (ClassInfo<FooBar>::isConfigurable)
{...}

This does what I originally wanted, which is to allow me to associate
meta-data with some arbitrary class, and have that accessible
throughout the code.

The problem is that since the above relies on static variables being
initialized at runtime, I cannot use any of the data as template
arguments. For example I'd like to be able to do the following :


template<class T, bool isConfigurable>
struct SomeAlgorithmImp
{
static void Func()
{
//...
};
};

template<class T>
struct SomeAlgorithmImp<T, true>
{
static void Func()
{
//...
};
};

template<class T>
struct SomeAlgorithm
{
static void Func()
{
SomeAlgorithmImp<T, ClassInfo<T>::isConfigurable>::Func();
}
};

SomeAlgorithm<FooBar>::Func();


The problem is that ClassInfo<T>::isConfigurable is not a 'compile
time constant expression'. (it actually can be used as a template
argument but only in the same translation unit as the definition of
the static variable - which limits its usefulness).

Any ideas on how I might be able to achieve this?

At some point I naively thought I can put the following in the header
instead of the translation unit :

template<> const bool ClassInfo<FooBar>::isConfigurable = false;

which of course works for using it as a template argument, but also
gives you multiple symbols during linking (yet bizarrely VC8 doesn't
seem to mind, g++ does).

I also tried making the ClassInfo class contain a struct which is
redifined per 'T', e.g.

template<class T>
struct ClassInfo
{
struct IsConfigurable;
};

then :
template<>
struct ClassInfo<Foo>::IsConfigurable
{
enum { Value = 1 };
};

This would have almost worked...had it not been for namespaces.
ClassInfo<T>::IsConfigurable must be defined in the same namespace as
ClassInfo...which in my case is impossible to guarantee.

I could also override the entire contents of ClassInfo. this would let
me to initialize integral types (like the int and bool members above)
within the class body thus avoiding the linker errors. However, this
approach also suffers from the namespace issues (the specialization of
a class must be in the same namespace as the class template itself)
(another thing that VC8 isn't too fussed about either!)

Any other ideas? At the moment I'm leaning towards trying to work
around my design's namespace complications , which would allow me to
use the child struct method above. Either that, or just go with a run
time solution to keep things simple.

Many thanks,

Bill
 
Reply With Quote
 
 
 
 
anon
Guest
Posts: n/a
 
      10-30-2008
greek_bill wrote:
> Hi,
>
> I'm trying to develop a system where I can register some data/
> information about a class. For example
>
> // ClassInfo.h
> template <class T>
> struct ClassInfo
> {
> static const std::string tagName;
> static const int version;
> static const bool isConfigurable;
> };
>
> // FooBar.h
> class FooBar {...};
>
> // FooBar.cpp
> template<> const std::string ClassInfo<FooBar>::tagName = "FooBar";
> template<> const int ClassInfo<FooBar>::version = 1;
> template<> const bool ClassInfo<FooBar>::isConfigurable = false;
>
> // main.cpp
> ...
> #include "FooBar.h"
> if (ClassInfo<FooBar>::isConfigurable)
> {...}
>
> This does what I originally wanted, which is to allow me to associate
> meta-data with some arbitrary class, and have that accessible
> throughout the code.
>


[...]

Does the next example demonstrates what you want?

#include <string>
#include <iostream>

struct A1
{
};
struct A2
{
};

template < class T >
struct At
{
};

template<>
struct At< A1 >
{
static std::string Get()
{
return "A1";
}
};
template<>
struct At< A2 >
{
static std::string Get()
{
return "A2";
}
};
int main()
{
std::cout << At< A1 >::Get() << std::endl;
}



 
Reply With Quote
 
 
 
 
greek_bill
Guest
Posts: n/a
 
      10-30-2008
>
> Does the next example demonstrates what you want?
>


No, not really. What you're doing is overriding (or rather providing)
Get() in a template specialization and the use that at run time. What
I'd like to do is override/provide something (e.g. an int or a bool)
in a template specialization and use that as a template argument at
compile time.
 
Reply With Quote
 
greek_bill
Guest
Posts: n/a
 
      11-02-2008
I like the partial base class specialization...good idea!

but I think it suffers from the same namespace problems. In my setup I
have something like :

namespace Core
{
// ClassInfo template definition here
}

namespace Extension
{
class Foo;

// Ideally I'd like to have the Foo specialization here
template<> ClassInfo<Foo> { ... };
}

The above fails to compile because the specialization of ClassInfo
appears in a different namespace ('Extension') than its definition. To
get this to work, I'd have to have the following :

namespace Extension
{
class Foo;
}

namespace Core
{
template<> ClassInfo<Extension::Foo> { ... };
}

While this is certainly possible, it forces a code layout restriction
that I'm not comfortable with. Ideally I'd like to keep the
specialization on Foo and Foo's definition as close as possible.

I admit, this isn't a huge problem, but if I could work around it that
I'd rather I did!


btw, I've moved on from this. What I did in the end is to 'discover'
whether a class is 'configurable' by checking for the presence of a
certain function. I find that discovering existing features (traits?)
of a class is generally easier than associating new ones (like I've
been describing above). Most of the relevant material I've read on
this topic (Modern C++, Boost::type_traits, etc) focus on discovering
features about a class.

Also, as it turns out, in my case it's better to decide whether a
class is configurable based on the presence of a Configure() function.
While I was trying to get the bool 'IsConfigurable' to work, I found
myself adding a static check (compile time assert) to ensure that if a
class is declared as configurable then it also provides a configure
function.

Anyway, thanks for the good idea though!

> Compile-time traits are a great tool.


Yes, they are!

Bill
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Meta-Meta-Programming, revisited Erik Veenstra Ruby 21 07-25-2006 10:26 PM
Meta-Meta-Programming Erik Veenstra Ruby 29 02-08-2006 08:22 PM
Meta methods to govern meta data? Duane Johnson Ruby 6 10-28-2005 03:57 AM
#if (defined(__STDC__) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) Oodini C Programming 1 09-27-2005 07:58 PM
META NAME and META HTTP-EQUIV Nym Pseudo HTML 1 09-26-2003 09:13 AM



Advertisments