How do static state a condition on a string literal inside a constexpr function?

The following example maincan static_assert, if the string literal begins with 'v', but verifycannot.

Why is this happening? Is there a way to allow conditions verifyto static_assertfor a character in a string literal?

#include <cstddef>

template <std::size_t N>
constexpr char get_first(const char (&str)[N])
{
    static_assert(N>1, "must be > 1");
    return str[0];
}

template <std::size_t N>
constexpr void verify(const char (&str)[N])
{
    static_assert(str[0] == 'v', "must start from v");   
}

int main()
{
    static_assert(get_first("value") == 'v', "first must be 'v'"); // succeeds
    verify("value"); // fails to compile
}

Compilation errors:

main.cpp: In instantiation of 'constexpr void verify(const char (&)[N]) [with long unsigned int N = 6]':
main.cpp:19:15:   required from here
main.cpp:13:9: error: non-constant condition for static assertion
         static_assert(str[0] == 'v', "must start from v");
         ^~~~~~~~~~~~~
main.cpp:13:9: error: 'str' is not a constant expression

An example .

+4
source share
3 answers

In C ++ 17, you can wrap a value in a constexpr lambda file ( online demo ). The call looks like

verify([=] { return "value"; });

and deploy you can

template <class StringWrapper>
constexpr void verify(StringWrapper str_w)
{
    constexpr auto str = str_w();
    static_assert(str[0] == 'v', "must start from v");   
}
+3
source

. static_assert, .

#include <type_traits>
template<bool b>
using enforce = std::bool_constant<b>;

template <std::size_t N>
constexpr int verify(const char (&str)[N])
{
    if(get_first(str) != 'v') {
        throw "must start from v";
    }
    return 0;
}

int main()
{
    using assertion = enforce<verify("value")>; // compiles
    using assertion = enforce<verify("fail")>; // fails to compile
    // or use it like
    constexpr auto assertion0 = verify("value"); // compiles
}

constexpr. , , :

26 : <source>:26:31: error: non-type template argument is not a constant expression
    using assertion = enforce<verify("fail")>; // fails to compile
                              ^~~~~~~~~~~~~~
15 : <source>:15:9: note: subexpression not valid in a constant expression
        throw "must start from v";
        ^
26 : <source>:26:31: note: in call to 'verify("fail")'
    using assertion = enforce<verify("fail")>; // fails to compile

constexpr verify, . .

+2

, verify()

template <std::size_t N>
constexpr void verify(const char (&str)[N])
{
    static_assert(str[0] == 'v', "must start from v");   
}

.

, , static_assert(), str, , , ( char of str ).

- EDIT -

OP .

, , , , .

template <char const * const str>
constexpr bool startWithUpperLetter ()
 { 
   static_assert( str[0] != 'v', "no start with \'v\', please" );

   return (str[0] >= 'A') && (str[0] <= 'Z');
 }

constexpr char const str1[] { "ABC" };
constexpr char const str2[] { "abc" };
constexpr char const str3[] { "vwx" };

int main ()
 {
   static_assert( startWithUpperLetter<str1>() == true, "!" );
   static_assert( startWithUpperLetter<str2>() == false, "!" );
   // static_assert( startWithUpperLetter<str3>() == false, "!" ); // error
 }
+1

Source: https://habr.com/ru/post/1687530/


All Articles