如何在由用来表示文字的字符类型参数化的模板中表达字符串文字? [英] How to express a string literal within a template parameterized by the type of the characters used to represent the literal?
问题描述
请考虑以下简单地图:
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
字符串.因此,我将其重写如下:
Now, suppose I need to make this map available both for char
and wchar_t
strings. So, I rewrite it as follows:
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
文字之间的差异.现在,我看到两个解决方案,都很难看.
And, of course, this does not work for C=wchar_t
. The problem is that I do not know how to template the difference between char
literals and wchar_t
literals. Right now I see two solutions, both ugly.
解决方案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"));
}
};
这很糟糕,因为整个逻辑都是重复的.
This is bad, because the whole logic is duplicated.
解决方案2 -解决方案之类的特征:
Solution 2 - a traits like solution:
#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
}
};
这样,我不需要复制逻辑,但这太冗长,并且严重依赖于宏.
This way I do not need to replicate the logic, but this is so verbose and relies heavily on macros.
必须有更好的方法;我只是看不到.
There must be a better way; I just do not see it.
我正在使用VS2010.
I am using VS2010.
编辑
我很高兴提出了一个更简单的解决方案-功劳归于 https://stackoverflow.com/users/5987/mark-ransom .不过,我必须进行一些小的修补才能使它编译:
I am glad that a much simpler solution is proposed - the credits go to https://stackoverflow.com/users/5987/mark-ransom. I had to make minor fixes to make it compile, though:
#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))
再次感谢.
推荐答案
使用宏生成字符串的两种形式,并使用模板函数选择要使用的形式.
Use a macro to generate both forms of the string, and a template function to choose which to use.
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, L##STR)
insert(value_type(CW(C, "in1"), CW(C, "out1")));
这篇关于如何在由用来表示文字的字符类型参数化的模板中表达字符串文字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!