【问题标题】:Defining string literal constants once both as char const* and wchar const*将字符串文字常量定义为 char const* 和 wchar const*
【发布时间】:2019-11-22 09:52:37
【问题描述】:

由于我正在使用的域的限制,我需要将字符串文字定义为 char const* 和 wchar const*,例如:

constexpr auto C_VAR_NAME_1 = "MY_VAR_NAME_1";
constexpr auto C_VAR_NAME_2 = "MY_VAR_NAME_2";
...

constexpr auto W_VAR_NAME_1 = L"MY_VAR_NAME_1";
constexpr auto W_VAR_NAME_2 = L"MY_VAR_NAME_2";
...

我有很多常量,我想避免定义两次相同的变量实际名称(这可能会导致一些拼写错误,因此名称不匹配),所以我使用了一些这样的宏:

#define WTEXT_IMPL(name) L##name
#define WTEXT(name)      WTEXT_IMPL(name)

#define MACRO_VAR_NAME_1 "MY_VAR_NAME_1"
#define MACRO_VAR_NAME_2 "MY_VAR_NAME_2"
...

constexpr auto C_VAR_NAME_1 = MACRO_VAR_NAME_1;
constexpr auto C_VAR_NAME_2 = MACRO_VAR_NAME_2;
...
constexpr auto W_VAR_NAME_1 = WTEXT(MACRO_VAR_NAME_1)
constexpr auto W_VAR_NAME_2 = WTEXT(MACRO_VAR_NAME_2)
...

这可行,但如果可能的话,我想摆脱宏的东西;所以我的问题是:是否可以在编译时使用没有宏的普通 C++ 标准来实现相同的结果?提前感谢您的帮助。

【问题讨论】:

    标签: c++ macros constexpr string-literals compile-time


    【解决方案1】:

    如果您只能将字符串文字限制为 ASCII 字符,则有一个不使用宏的简单解决方案(在 C++17 版本中):

    template<std::size_t N>
    struct DoubleStringLiteral {
        constexpr DoubleStringLiteral(const char(&s)[N])
        {
            for (size_t i=0; i<N; ++i) {
                if (s[i] < 0) throw std::invalid_argument("None ASCII character are not supported!");
                str[i] = s[i];
                wstr[i] = static_cast<wchar_t>(s[i]);
            }
        }
    
        constexpr std::string_view view() const
        {
            return { str };
        }
    
        constexpr std::string_view wview() const
        {
            return { wstr };
        }
    
        char str[N];
        wchar_t wstr[N];
    };
    
    constexpr DoubleStringLiteral a{ "Demo!" };
    constexpr DoubleStringLiteral b{ R"(Raw!
    str
    sample)" };
    

    Demo

    对于 C++11 应该是可行的,但是需要大量的样板代码。

    这里是C++14 version

    【讨论】:

    • 太棒了!我认为这个解决方案肯定解决了我的问题(是的,我只需要 ASCII 字符);非常感谢!
    【解决方案2】:

    我会这样做:

    #include <string_view>
    
    struct DoubleStringLiteral {
        std::string_view str;
        std::wstring_view wstr;
    };
    
    #define DOUBLE_LITERAL(name, value) \
        constexpr DoubleStringLiteral name { \
            value, \
            L ## value \
        }
    

    Demo

    【讨论】:

    • 仍然使用宏,只是尽量减少重复。
    • 查看其他答案。
    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 2010-09-21
    相关资源
    最近更新 更多