最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Compile time check if string contains quotes - Stack Overflow

programmeradmin0浏览0评论

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.

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.

Share Improve this question edited Mar 6 at 10:17 cigien 60.6k11 gold badges82 silver badges121 bronze badges asked Mar 6 at 8:16 gladesglades 4,9982 gold badges22 silver badges64 bronze badges 1
  • Or with std::string_view i.o. a template over N : godbolt./z/aeMqevE3x – Pepijn Kramer Commented Mar 6 at 8:35
Add a comment  | 

2 Answers 2

Reset to default 4

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.

Function parameters are not constant expression, even in constexpr/consteval function.

Possibility is to use char sequence instead of string.

gcc/clang have an extension to allow to build UDL from literal string:

// That template uses the extension
template<typename Char, Char... Cs>
constexpr auto operator"" _cs() -> std::integer_sequence<Char, Cs...> {
    return {};
}

See my answer from String-interning at compiletime for profiling to have MAKE_STRING macro if you cannot used the extension (Really more verbose, and hard coded limit for accepted string length).

then

struct JsonKey
{
    template <char... Cs>
    constexpr JsonKey(std::integer_sequence<char, Cs...>)
    {
        constexpr char str[] = {Cs..., 0};
        static_assert(check_no_quotes(str), "Can't have quotes");
    }
};

JsonKey jsonKey("json_key_without_quotes"_cs);

Demo

发布评论

评论列表(0)

  1. 暂无评论