有什么方法可以编译时检查字符串用户定义的文字吗?
Is there any way for compile-time check of string user-defined literal?
我正在编写一个用户定义的 string
文字来将月份名称转换为数字。此文字的预期用法类似于
"Nov"_m
哪个应该 return 11
.
目前我的代码看起来像
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)
是一个进行实际转换的函数(如果月份名称不正确,则为 returns -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);
}
但这不起作用,因为编译器不确定 convert_month_to_int(str, len)
是否为常量表达式。
有什么方法可以实现这种行为吗?
我同意改用枚举的建议。
但是无论如何,在 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";
}
例如,另见 this question。
我以不同的方式解决了这个问题,既不使用枚举也不使用字符串文字,即使未按 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.
}
我使用的方法是定义一个class type month
which is documented to be a literal class type.
然后我create constexpr
instances of each month:
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。 constexpr
位在 VS 中损坏,但其他一切正常,包括在编译时检测错误的月份名称。
我正在编写一个用户定义的 string
文字来将月份名称转换为数字。此文字的预期用法类似于
"Nov"_m
哪个应该 return 11
.
目前我的代码看起来像
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)
是一个进行实际转换的函数(如果月份名称不正确,则为 returns -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);
}
但这不起作用,因为编译器不确定 convert_month_to_int(str, len)
是否为常量表达式。
有什么方法可以实现这种行为吗?
我同意改用枚举的建议。
但是无论如何,在 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";
}
例如,另见 this question。
我以不同的方式解决了这个问题,既不使用枚举也不使用字符串文字,即使未按 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.
}
我使用的方法是定义一个class type month
which is documented to be a literal class type.
然后我create constexpr
instances of each month:
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。 constexpr
位在 VS 中损坏,但其他一切正常,包括在编译时检测错误的月份名称。