2012-01-27 33 views
10

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ả charwchar_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.

+0

+1 Đẹp nhất. :) –

+2

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

Trả lời

9

Sử dụng macro để tạo cả hai dạng chuỗi và chức năng mẫu để chọn sử dụng.

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"))); 
+0

Đơn giản, vì tất cả điều đó đều có tính di truyền. Đoạn mã của bạn yêu cầu một số chỉnh sửa để làm cho nó biên dịch - đăng chúng như một chỉnh sửa cho câu hỏi của tôi. Nhưng nếu không - chỉ đơn giản là tuyệt vời. – mark

+0

@mark, cảm ơn vì các kudo và cảm ơn vì đã chỉ ra các lỗi trong mã của tôi. Tôi hy vọng điều này bây giờ biên dịch, mặc dù nó không giống với của bạn. –

-1

Làm cho tất cả các hằng chuỗi các thành viên tĩnh, một cái gì đó như thế này:

#include "stddef.h" 
#include "stdio.h" 
template<class C> 
class String 
{ 
    public: 
    String(const C* value = defVal) : mValue(value) {} 
    const C* valueOf() { return mValue; } 
    private: 
    const C* mValue; 
    static const C defVal[]; 
}; 
const char String<char>::defVal[] = "char"; 
const wchar_t String<wchar_t>::defVal[] = L"wchar_t"; 
int main(int argc, char **argv) 
{ 
    String<char> c(*argv); 
    String<wchar_t> w; 
    return printf("%S\n", w.valueOf()); 
} 

Bạn có thể có thể macroise các định nghĩa để tránh sao chép chúng.

+0

Đó không phải là chính xác những gì ông đã làm? –

Các vấn đề liên quan