What is the cheapest way to specialize a feature item
I have a trait class that only needs to provide one information about the other types (as a string):
template<typename T>
struct some_traits {
static const char* const some_string;
};
I need to provide special instances some_string
for each type. The usual way I know how to do this is to declare only some_traits
and then write specializations:
template<typename T>
struct some_traits;
template<>
struct some_traits<blah> {
static const char* const some_string;
};
const char* const some_traits<blah>::some_string = "blah string";
It is, however, a lot of code when I only need specialized ones some_string
. Is there a way to simplify this?
I tried messing around with explicit specializations, but couldn't come up with a syntax that didn't make the compiler splash poisonous error messages on my face.
Notes:
- I know I can hide this behind a macro. I'm still curious.
- This is required to compile on an embedded platform with GCC 4.1. So C ++ 03 is all we have. (Boost is ok, but for limited Posix support, we're stuck with 1.52, if that matters.)
source to share
You can explicitly specialize elements of class templates:
template<typename T>
struct some_traits {
static const char* const some_string;
};
template<>
char const* const some_traits<int>::some_string = "int";
This should reduce the overhead with minor announcements of new specializations. However, this method cannot be applied to partial specializations:
template<typename T> struct foo {};
template<typename T>
char const* const some_traits<foo<T>>::some_string = "foo<T>"; // error
... that is, unless you add partial specialization for some_traits
:
template<typename T>
struct some_traits<foo<T>> {
char const* const some_string;
};
Two alternatives:
(1) Using ADL and functions
template<typename T> struct some_string_tag {};
template<typename T>
struct some_traits {
static const char* const some_string;
};
template<typename T>
char const* const some_traits<T>::some_string = get_string(some_string_tag<T>());
The specialization can then be written as:
char const* get_string(some_string_tag<int>) { return "int"; }
And partial specializations like:
template<typename T>
char const* get_string(some_string_tag<foo<T>>) { return "foo<T>"; }
(In this case some_traits
, this is the point to customize how the string is found, and provides convenient access to the string as a variable.)
(2) Second trait using built-in function
template<typename T>
char const* const some_traits<T>::some_string = some_traits_X<T>::get_string();
template<typename T> struct some_traits_X {
// provide: static char const* get_string();
};
template<>
struct some_traits_X<int> {
static char const* get_string() { return "int"; }
};
template<typename T>
struct some_traits_X<foo<T>> {
static char const* get_string() { return "foo<T>"; }
};
source to share