Reputation: 224079
I have a traits class that is supposed to provide just one information about other types (in form of a string):
template<typename T>
struct some_traits {
static const char* const some_string;
};
I need to provide special instances of some_string
for each type. The common way I know how to do this is to only declare 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";
This is, however, a lot of code, when all I need is a specialized some_string
. Is there a way to simplify this?
I have tried to fiddle with explicit specializations, but failed to come up with a syntax that doesn't make the compiler spit venomous error messages into my face.
Notes:
Upvotes: 3
Views: 94
Reputation: 39111
It is possible to explicitly specialize members 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 of declaring new specializations slightly. However, this technique 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 a 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>());
A specialization can then be written as:
char const* get_string(some_string_tag<int>) { return "int"; }
And partial specializations as:
template<typename T>
char const* get_string(some_string_tag<foo<T>>) { return "foo<T>"; }
(In this case, some_traits
is a point for customizing how the string is found, and it provides convenient access to the string as a variable.)
(2) A second trait using an inline 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>"; }
};
Upvotes: 7
Reputation: 3092
Why not use functions?
template<typename T>
struct some_traits {
static const char* const some_string();
};
template<>
struct some_traits<blah> {
static const char* const some_string() { return "blah string"; }
};
Upvotes: -1