使特征成员专业化的最便宜方法是什么

What's the cheapest way to specialize a traits member

提问人:sbi 提问时间:7/18/2015 最后编辑:dypsbi 更新时间:7/18/2015 访问量:89

问:

我有一个特征类,它应该只提供有关其他类型的一个信息(以字符串的形式):

template<typename T>
struct some_traits {
    static const char* const some_string;
};

我需要为每种类型提供特殊实例。我知道如何做到这一点的常见方法是只声明,然后编写专业化:some_stringsome_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

我试图摆弄显式的专用化,但未能想出一种不会让编译器向我吐出有毒错误消息的语法。

笔记:

  • 我知道我可以把它隐藏在宏后面。我仍然很好奇。
  • 这需要在具有 GCC 4.1 的嵌入式平台上进行编译。所以C++03就是我们所拥有的一切。(Boost 很好,但对于有限的 Posix 支持,我们只能使用 1.52,以防万一。
C++ 模板 专用化 类型特征 C++03

评论

0赞 dyp 7/18/2015
你只需要完整的专业化吗?coliru.stacked-crooked.com/a/d47849e14289149b
0赞 m.s. 7/18/2015
您需要多少个专业?
0赞 sbi 7/18/2015
@dyp:是的,那可以。我以为你不能专门化类模板成员?
0赞 sbi 7/18/2015
(顺便说一句,@dyp,如果你把这个评论变成一个答案,你会得到我的赞成票,如果没有其他人提出更好的建议,你就会接受。
0赞 dyp 7/18/2015
可以显式地专用化“类模板”的成员。请注意,显式专用化要求将所有封闭模板解析为实际类型/函数,因此您实际上(重新)定义特定类(模板实例化)的成员,而不是泛型(未实例化)类模板的成员。

答:

-1赞 Benilda Key 7/18/2015 #1

为什么不使用函数?

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"; }
};

评论

0赞 sbi 7/18/2015
因为一般来说,常量比函数调用更普遍可用?(顺便说一句,如果我这样做,我只会声明主模板,而不会定义它。
7赞 dyp 7/18/2015 #2

可以显式地对类模板的成员进行专用化:

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>"; }
};

评论

0赞 sbi 7/18/2015
我发现,一般来说,常量比函数调用更普遍有用(参见)。对于字符串来说,它很可能没有太大的区别,但无论如何我都想知道如何做到这一点。std::numeric_limits<>::max()
0赞 dyp 7/18/2015
@sbi 这是第二个特征,只是为了提供字符串。你仍然可以把你原来的特质作为一个“适配器”。请参阅我更新的答案。如果您有几个特征都需要专业化,这可能会更方便。
0赞 sbi 7/18/2015
明白了。这个答案很全面。谢谢!