有什么方法可以在编译时检查字符串用户定义的文字吗

Is there any way for compile-time check of string user-defined literal?

本文关键字:用户 字符串 定义 文字 检查 方法 什么 编译      更新时间:2023-10-16

我正在编写一个用户定义的string文字,用于将月份名称转换为数字。这个文字的预期用法有点像

"Nov"_m

其应当返回CCD_ 2。

目前我的代码看起来像

constexpr Duration operator ""_m(const char* str, size_t len)
{
    return convert_month_to_int(str, len);
}

其中constexpr int convert_month_to_int(const char, size_t)是进行实际转换的函数(或者如果月份名称不正确则返回-1(。

问题是,如果传递给这个文本的字符串没有命名任何月份,我想显示某种编译错误。我尝试以以下方式使用static_assert

constexpr Duration operator ""_m(const char* str, size_t len)
{
    static_assert(convert_month_to_int(str, len) > 0, "Error");
    return convert_month_to_int(str, len);
}

但这不起作用,因为编译器不确定CCD_。

有什么方法可以实现这种行为吗?

我以不同的方式处理了这个问题,既不使用枚举也不使用字符串文字,即使没有构造为constexpr:,也会检测到错误的月份名称

#include "date.h"
int
main()
{
    using namespace date::literals;
    auto m1 = nov;                           // ok
    static_assert(unsigned{nov} == 11, "");  // ok
    auto m2 = not_a_month;
    test.cpp:86:15: error: use of undeclared identifier 'not_a_month'
        auto m2 = not_a_month;
                  ^
    1 error generated.
}

我使用的方法是定义一个类类型month,它被记录为文本类类型。

然后我创建每个月的constexpr实例:

CONSTDATA date::month jan{1};
CONSTDATA date::month feb{2};
CONSTDATA date::month mar{3};
CONSTDATA date::month apr{4};
CONSTDATA date::month may{5};
CONSTDATA date::month jun{6};
CONSTDATA date::month jul{7};
CONSTDATA date::month aug{8};
CONSTDATA date::month sep{9};
CONSTDATA date::month oct{10};
CONSTDATA date::month nov{11};
CONSTDATA date::month dec{12};

(CONSTDATA是一个宏,用于帮助C++11 constexpr不太支持的编译器(

我在一周中的几天里也使用了同样的技巧。

以上都是用clang和-std=c++11编译的。它还将与gcc合作。VS中的constexpr位已损坏,但其他一切都正常,包括在编译时检测错误的月份名称。

我同意使用枚举的建议。

但无论如何,在constexpr函数中发出这样错误信号的常用方法是抛出异常。

constexpr Duration operator ""_m(const char* str, size_t len)
{
    return convert_month_to_int(str, len) > 0 ? convert_month_to_int(str, len) : throw "Error";
}

例如,另请参见此问题。