I want to assert that an object JsonKey
if constructed with a string that is known at compile time doesn't contain a quote. Here's what I have:
#include<iostream>
template <size_t N>
constexpr bool check_no_quotes(const char (&str)[N])
{
for (size_t i = 0; i < N; i++) // Initialize 'i' here
{
if (str[i] == '"') // No need for the backslash here
return false;
}
return true;
}
struct JsonKey
{
template <size_t N>
constexpr JsonKey(const char (&str)[N])
{
static_assert(check_no_quotes(str), "Can't have quotes");
}
};
int main()
{
// This will compile because it does not contain quotes
JsonKey("json_key_without_quotes");
// This will fail to compile because it contains quotes
// JsonKey("json key with \"quotes\""); // Uncommenting this will trigger the static_assert error
return 0;
}
The error I get:
<source>: In instantiation of 'constexpr JsonKey::JsonKey(const char (&)[N]) [with long unsigned int N = 24]':
<source>:26:38: required from here
26 | JsonKey("json_key_without_quotes");
| ^
<source>:19:38: error: non-constant condition for static assertion
19 | static_assert(check_no_quotes(str), "Can't have quotes");
| ~~~~~~~~~~~~~~~^~~~~
<source>:19:38: in 'constexpr' expansion of 'check_no_quotes<24>((* & str))'
<source>:8:16: error: 'str' is not a constant expression
8 | if (str[i] == '"') // No need for the backslash here
| ~~~^
Compiler returned: 1
I don't get why str
is not compile-time available here.
You can't static_assert
on str
because function arguments are not usable as constant expressions. See Can't use function parameter of a constexpr function in a constant expression for an explanation.
To achieve what you want, you can simply assert that the condition holds, and to ensure that it is a compile time check, make the constructor consteval
.
struct JsonKey
{
consteval JsonKey(std::string_view str)
{
assert(not std::ranges::contains(str, '"') && "Can't have quotes");
}
};
demo.
Also, just use std::string_view
as the parameter, and use a standard algorithm instead of writing it yourself.