G
greek_bill
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
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