Hãy xem xét các bản đồ đơn giản sau đây:Làm cách nào để diễn tả chuỗi ký tự trong một mẫu được tham số hóa theo loại ký tự được sử dụng để biểu diễn chữ?
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"));
}
};
Bây giờ, giả sử tôi cần phải thực hiện bản đồ này có sẵn cho cả char
và wchar_t
chuỗi. Vì vậy, tôi viết lại nó như sau:
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"));
}
};
Và, tất nhiên, điều này không làm việc cho C=wchar_t
. Vấn đề là tôi không biết làm thế nào để mẫu sự khác biệt giữa char
literals và wchar_t
literals. Ngay bây giờ tôi thấy hai giải pháp, cả hai đều xấu xí.
Giải pháp 1 - chuyên MyCoolMap
bởi wchar_t
:
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"));
}
};
này là xấu, bởi vì toàn bộ logic được nhân đôi.
Giải pháp 2 - một đặc điểm như giải pháp:
#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
}
};
Bằng cách này tôi không cần phải sao chép logic, nhưng điều này là quá dài dòng và dựa chủ yếu vào các macro.
Phải có cách tốt hơn; Tôi chỉ không nhìn thấy nó.
Tôi đang sử dụng VS2010.
EDIT
Tôi vui mừng rằng một giải pháp đơn giản hơn nhiều được đề xuất - các khoản tín dụng đi đến https://stackoverflow.com/users/5987/mark-ransom. Tôi đã phải thực hiện các sửa chữa nhỏ để biên dịch, mặc dù:
#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))
Xin cảm ơn một lần nữa.
+1 Đẹp nhất. :) –
Vấn đề của bạn là trong khi hai danh sách các chuỗi * giống nhau *, chúng không thực sự giống nhau. – egrunin