I have a user-defined literal operator that only makes sense for strings of a specific length, like this:
constexpr uint16_t operator "" _int(const char* s, std::size_t len)
{
return len == 2 ? s[0] | (s[1] << 8) : throw;
}
This works:
"AB"_int // equals 16961
But this also compiles, and I don't want it to:
"ABC"_int // throws at runtime
I tried static_assert(len == 2)
, but it isn't allowed in a constexpr function.
How can I make "ABC"_int
cause an error at compile time?
How can I make
"ABC"_int
cause an error at compile time?
By example: initialize a constexpr
variable
constexpr auto foo = "ABC"_int;
Otherwise (if you don't force the compile time calculation in some way) the compiler doesn't compute (not mandatory but, in fact, is what happens) compile time but prepare the code for the run-time compilation.
Before C++20, you can wrap std::integral_constant
with a macro to make throw
trigger a compile error.
constexpr uint16_t operator "" _int(const char* s, std::size_t len)
{
return len == 2 ? s[0] | (s[1] << 8) : throw;
}
void test()
{
#define FORCE_CONSTANT(val) std::integral_constant<decltype(val), (val)>::value
FORCE_CONSTANT("AB"_int);
// FORCE_CONSTANT("ABC"_int); // error, expected compile-time constant expression
}
And things become easy since C++20, user-defined literals are allowed to be string literal operator template
. (cppref)
So, the following code will work as you expect.
template <size_t kCount>
struct template_str_buffer
{
using char_type = char;
consteval template_str_buffer(const char_type(&str)[kCount]) noexcept
{
for (size_t i = 0; i < kCount; ++i) {
data[i] = str[i];
}
}
char_type data[kCount];
constexpr static size_t count = kCount - sizeof(char_type);
};
template <template_str_buffer kStrBuf>
consteval uint16_t operator""_int()
{
static_assert(kStrBuf.count == 2);
return kStrBuf.data[0] | (kStrBuf.data[1] << 8);
}
void test()
{
"AB"_int;
// "ABC"_int; // static assertion failed
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With