マルチ文字列リテラル

以下、cppll に投稿した内容と同文。

Windows プログラミングではよく LPCTSTR, TCHAR, _T などのマクロを利用して、ANSI文字列(多バイト文字列), UNICODE文字列のどちらでも対応できるようにしますが、これはどちらか片方のインスタンスが作成されればいいケースであって、C++ のテンプレートを利用してANSI文字列(多バイト文字列), UNICODE文字列のそれぞれに対応したインスタンスを両方とも用意したい場合に LPCTSTR, TCHAR のマクロに相当する部分はそのままテンプレートで処理できるのですが、_T マクロに相当する部分がちと面倒なことになってしまいます。

そこで、_T マクロに相当する以下のような _TX ギミックを用意してみました。

#if !defined(_TX)
class TX_char_literal_holder
{
public:
    const char char_literal;
    const wchar_t wchar_t_literal;
    TX_char_literal_holder
    (
        const char a_char_literal,
        const wchar_t a_wchar_t_literal
    )
        :char_literal(a_char_literal)
        ,wchar_t_literal(a_wchar_t_literal)
    {
    }
    operator const char () const
    {
        return char_literal;
    }
    operator const wchar_t () const
    {
        return wchar_t_literal;
    }
};
class TX_string_literal_holder
{
public:
    const char *char_literal;
    const wchar_t *wchar_t_literal;
    TX_string_literal_holder
    (
        const char *a_char_literal,
        const wchar_t *a_wchar_t_literal
    )
        :char_literal(a_char_literal)
        ,wchar_t_literal(a_wchar_t_literal)
    {
    }
    operator const char * () const
    {
        return char_literal;
    }
    operator const wchar_t * () const
    {
        return wchar_t_literal;
    }
};
inline TX_char_literal_holder TX_literal_holder
(
    const char a_char_literal,
    const wchar_t a_wchar_t_literal
)
{
    return TX_char_literal_holder(a_char_literal, a_wchar_t_literal);
}
inline TX_string_literal_holder TX_literal_holder
(
    const char *a_char_literal,
    const wchar_t *a_wchar_t_literal
)
{
    return TX_string_literal_holder(a_char_literal, a_wchar_t_literal);
}
#define _TX(X) TX_literal_holder(X, L##X)
#endif

...以下はこの _TX ギミックの利用例です。

#define _WIN32_WINNT 0x0500
#include<windows.h>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "kernel32.lib")

inline void msg_box(const char *msg, const char *title, UINT flags)
{
    MessageBoxA(GetConsoleWindow(), msg, title, flags);
}
inline void msg_box(const wchar_t *msg, const wchar_t *title, UINT flags)
{
    MessageBoxW(GetConsoleWindow(), msg, title, flags);
}

template<class char_T>
inline void msg_box(const char_T *msg, UINT flags)
{
    msg_box(msg, _TX("マルチ文字列リテラル"), flags);
}

int main(int argc, char *args[])
{
    argc, args;
    msg_box("char message", MB_ICONINFORMATION |MB_OK);
    msg_box(L"wchar_t message", MB_ICONINFORMATION |MB_OK);
    return EXIT_SUCCESS;
}

■追記

wraith13 『TX_char_literal_holder クラスと TX_string_literal_holder クラスはクラステンプレートで一まとめにしたほうがよかったかな。』

ということでクラステンプレートにしてみました。

#if !defined(_TX)
template<class char_T, class wide_T>
class TX_literal_holder
{
public:
    char_T char_literal;
    wide_T wide_literal;
    TX_literal_holder(char_T a_char_literal, wide_T a_wide_literal)
        :char_literal(a_char_literal), wide_literal(a_wide_literal)
    {
    }
    operator char_T () const
    {
        return char_literal;
    }
    operator wide_T () const
    {
        return wide_literal;
    }
};
inline TX_literal_holder<const char, const wchar_t> make_TX_literal_holder
(
    const char a_char_literal,
    const wchar_t a_wide_literal
)
{
    return TX_literal_holder<const char, const wchar_t>
    (
        a_char_literal,
        a_wide_literal
    );
}
inline TX_literal_holder<const char *, const wchar_t *> make_TX_literal_holder
(
    const char * a_char_literal,
    const wchar_t * a_wide_literal
)
{
    return TX_literal_holder<const char *, const wchar_t *>
    (
        a_char_literal,
        a_wide_literal
    );
}
#define _TX(X) make_TX_literal_holder(X, L##X)
#endif