User defined class meta data (type traits?)

Discussion in 'C++' started by greek_bill, Oct 29, 2008.

  1. greek_bill

    greek_bill Guest

    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
     
    greek_bill, Oct 29, 2008
    #1
    1. Advertising

  2. greek_bill

    anon Guest

    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;
    }
     
    anon, Oct 30, 2008
    #2
    1. Advertising

  3. greek_bill

    greek_bill Guest

    >
    > 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.
     
    greek_bill, Oct 30, 2008
    #3
  4. greek_bill

    greek_bill Guest

    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
     
    greek_bill, Nov 2, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Oodini
    Replies:
    1
    Views:
    1,788
    Keith Thompson
    Sep 27, 2005
  2. Diego Martins
    Replies:
    5
    Views:
    488
    Diego Martins
    Sep 5, 2006
  3. ray
    Replies:
    1
    Views:
    1,339
    Robert Kern
    Jun 4, 2010
  4. Duane Johnson

    Meta methods to govern meta data?

    Duane Johnson, Oct 25, 2005, in forum: Ruby
    Replies:
    6
    Views:
    247
    Adam Sanderson
    Oct 28, 2005
  5. Ara.T.Howard
    Replies:
    4
    Views:
    113
    Duane Johnson
    Nov 2, 2005
Loading...

Share This Page