c++stringc++17constexprcompile-time

Compile time check if string contains quotes


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:

LiveDemo

#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.


Solution

  • 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.