考虑下面这个简单的地图:
class MyCoolMap : public unordered_map<const char *, const char *>
{
public:
ProtoTypeMap()
{
insert(value_type("in1", "out1"));
insert(value_type("in2", "out2"));
...
insert(value_type("inN", "outN"));
}
};
现在,假设我需要同时为char
和wchar_t
字符串使用这个映射表。因此,我将其重写如下:
template<class C>
class MyCoolMap : public unordered_map<const C *, const C *>
{
public:
MyCoolMap()
{
insert(value_type("in1", "out1"));
insert(value_type("in2", "out2"));
...
insert(value_type("inN", "outN"));
}
};
当然,这对于 C=wchar_t
是不起作用的。问题在于我不知道如何模板化 char
字面量和 wchar_t
字面量之间的差异。现在我看到两个解决方案,都很丑陋。
解决方案1 - 通过 wchar_t
特化 MyCoolMap
:
template<>
class MyCoolMap<wchar_t> : public unordered_map<const wchar_t *, const wchar_t *>
{
public:
MyCoolMap()
{
insert(value_type(L"in1", L"out1"));
insert(value_type(L"in2", L"out2"));
...
insert(value_type(L"inN", L"outN"));
}
};
这样做是不好的,因为整个逻辑都被复制了。
解决方案2 - 像traits一样的解决方案:
#define _TOWSTRING(x) L##x
#define TOWSTRING(x) _TOWSTRING(x)
template <class C, int> struct special_string;
#define DECL_SPECIAL_STRING(STR) \
const int ss_##STR = __LINE__; \
template<> struct special_string<char, ss_##STR> { static const char *get_value() { return #STR; } }; \
template<> struct special_string<wchar_t, ss_##STR> { static const wchar_t *get_value() { return TOWSTRING(#STR); } };
DECL_SPECIAL_STRING(in1)
DECL_SPECIAL_STRING(out1)
DECL_SPECIAL_STRING(in2)
DECL_SPECIAL_STRING(out2)
...
DECL_SPECIAL_STRING(inN)
DECL_SPECIAL_STRING(outN)
template<class C>
class MyCoolMap : public unordered_map<const C *, const C *>
{
public:
MyCoolMap()
{
#define INSERT_MAPPING(in, out) insert(value_type(special_string<C, ss_##in>::get_value(), special_string<C, ss_##out>::get_value()))
INSERT_MAPPING(in1, out1);
INSERT_MAPPING(in2, out2);
...
INSERT_MAPPING(inN, outN);
#undef INSERT_MAPPING
}
};
这种方法不需要复制逻辑,但非常冗长,且 heavily relies on macros(宏)。
一定有更好的方法,我只是没看出来。
我正在使用 VS2010。
编辑
很高兴有一个更简单的解决方案被提出 - 鸣谢 https://stackoverflow.com/users/5987/mark-ransom。不过,我必须做一些小修改才能使其编译:
#define _TOWSTRING(x) L##x
#define TOWSTRING(x) _TOWSTRING(x)
template<typename C> const C * ChooseCW(const char * c, const wchar_t * w);
template<> const char * ChooseCW<char>(const char * c, const wchar_t * w)
{
return c;
}
template<> const wchar_t *ChooseCW<wchar_t>(const char * c, const wchar_t * w)
{
return w;
}
#define CW(C, STR) ChooseCW<C>(#STR, TOWSTRING(#STR))
再次感谢。