使特征成员专业化的最便宜的方法是什么
What's the cheapest way to specialize a traits member
我有一个特征 class 应该只提供一个关于其他类型的信息(以字符串的形式):
template<typename T>
struct some_traits {
static const char* const some_string;
};
我需要为每种类型提供 some_string
的特殊实例。我知道如何做到这一点的常用方法是仅声明 some_traits
,然后编写特化:
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";
然而,这是很多代码,而我只需要一个专门的 some_string
。有没有办法简化这个?
我曾尝试 fiddle 使用显式特化,但未能提出一种不会让编译器向我吐出恶毒错误消息的语法。
备注:
- 我知道我可以将其隐藏在宏后面。我还是很好奇。
- 这需要在带有 GCC 4.1 的嵌入式平台上编译。所以我们只有 C++03。 (提升很好,但对于有限的 Posix 支持,我们坚持使用 1.52,以防万一。)
为什么不用函数?
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"; }
};
可以显式特化 class 模板的成员:
template<typename T>
struct some_traits {
static const char* const some_string;
};
template<>
char const* const some_traits<int>::some_string = "int";
这应该会稍微减少声明新专业化的开销。但是,此技术不能应用于部分专业化:
template<typename T> struct foo {};
template<typename T>
char const* const some_traits<foo<T>>::some_string = "foo<T>"; // error
... 也就是说,除非您为 some_traits
添加部分专业化:
template<typename T>
struct some_traits<foo<T>> {
char const* const some_string;
};
两种选择:
(1) 使用 ADL 和函数
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>());
专业化可以写成:
char const* get_string(some_string_tag<int>) { return "int"; }
部分专业化为:
template<typename T>
char const* get_string(some_string_tag<foo<T>>) { return "foo<T>"; }
(在这种情况下,some_traits
是自定义如何找到字符串的一个点,它提供了对字符串作为变量的方便访问。)
(2) 使用内联函数的第二个特征
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>"; }
};
我有一个特征 class 应该只提供一个关于其他类型的信息(以字符串的形式):
template<typename T>
struct some_traits {
static const char* const some_string;
};
我需要为每种类型提供 some_string
的特殊实例。我知道如何做到这一点的常用方法是仅声明 some_traits
,然后编写特化:
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";
然而,这是很多代码,而我只需要一个专门的 some_string
。有没有办法简化这个?
我曾尝试 fiddle 使用显式特化,但未能提出一种不会让编译器向我吐出恶毒错误消息的语法。
备注:
- 我知道我可以将其隐藏在宏后面。我还是很好奇。
- 这需要在带有 GCC 4.1 的嵌入式平台上编译。所以我们只有 C++03。 (提升很好,但对于有限的 Posix 支持,我们坚持使用 1.52,以防万一。)
为什么不用函数?
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"; }
};
可以显式特化 class 模板的成员:
template<typename T>
struct some_traits {
static const char* const some_string;
};
template<>
char const* const some_traits<int>::some_string = "int";
这应该会稍微减少声明新专业化的开销。但是,此技术不能应用于部分专业化:
template<typename T> struct foo {};
template<typename T>
char const* const some_traits<foo<T>>::some_string = "foo<T>"; // error
... 也就是说,除非您为 some_traits
添加部分专业化:
template<typename T>
struct some_traits<foo<T>> {
char const* const some_string;
};
两种选择:
(1) 使用 ADL 和函数
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>());
专业化可以写成:
char const* get_string(some_string_tag<int>) { return "int"; }
部分专业化为:
template<typename T>
char const* get_string(some_string_tag<foo<T>>) { return "foo<T>"; }
(在这种情况下,some_traits
是自定义如何找到字符串的一个点,它提供了对字符串作为变量的方便访问。)
(2) 使用内联函数的第二个特征
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>"; }
};