Reading some source code, I have found next traits definition:
namespace dds {
template <typename Topic> struct topic_type_support { };
template <typename Topic> struct topic_data_writer { };
template <typename Topic> struct topic_data_reader { };
template <typename Topic> struct topic_data_seq { };
}
#define REGISTER_TOPIC_TRAITS(TOPIC) \
namespace dds { \
template<> struct topic_type_support<TOPIC> { \
typedef TOPIC##TypeSupport type; }; \
template<> struct topic_data_writer<TOPIC> { \
typedef TOPIC##DataWriter type; }; \
template<> struct topic_data_reader<TOPIC> { \
typedef TOPIC##DataReader type; }; \
template<> struct topic_data_seq<TOPIC> { \
typedef TOPIC##Seq type; }; \
}
That looks weird to me. I would have grouped all the traits in a unique class like this:
namespace dds {
template <typename Topic> struct topic_traits { };
}
#define REGISTER_TOPIC_TRAITS(TOPIC) \
namespace dds { \
template<> struct topic_traits<TOPIC> { \
typedef TOPIC##TypeSupport type_support; \
typedef TOPIC##DataWriter data_writter; \
typedef TOPIC##DataReader data_reader; \
typedef TOPIC##Seq seq_type; \
}; \
}
Can any of you figure out why second approach could be more fragile than the first one or significantly harder to add new traits?
Having a single template class is now called a "traits blob". "Traits blob" are not recommended as they do not work well with meta-function (i.e. compile-time functions).
A meta-function is a template that takes a class and performs some operation on it. Something like:
template <class T>
class metafunction
{
typename T::type value = ...;
}
You can then call the meta function for any of your traits by doing:
metafunction<topic_type_support<int> >::value;
metafunction<topic_data_writer<int> >::value;
You would not be able to call the meta-function with your traits blob class because there is now way to tell the metafunction which typedef to use.
If you want to learn more about meta-functions, I recommend the book C++ Template Metaprogramming.