0

i search didn't find much about constexpr function. C++ primer says the return type and the type of each parameter in a must be a literal type. And now return type i use bool and parameters type i use reference.but in the return i use two basic_string function to calculation results.clion is tell me can't use basic_string function in constexpr function

constexpr bool a (const string &z , const string &zz)
{
    return (z.size() > zz.size());
}

Thank you very much for answering my question!

Nater
  • 165
  • 7
  • 1
    The problem is that, IIRC, `std::string` simply has no `constexpr` constructors until at least C++20 (inclusive). You could probably use a `std::string_view` instead. – Konrad Rudolph Jan 24 '20 at 09:03

2 Answers2

1

You are right that all the types you used are literal types, but there is another requirement for a constexpr function.

A constexpr function must be callable for at least one set of arguments so that the call is a constant expression.

The problem is that z.size() can never be called in a constant expression, because string's size function is not declared constexpr.

If a function declared constexpr can never be used as a constant expression, then the program has undefined behavior and the compiler may or may not warn or print an error about it.

If you change the function in a way that can be used as a constant expression for at least one set of call arguments, then there will be no error on the definition anymore:

constexpr bool a (bool b, const string &z , const string &zz)
{
    return b ? false : (z.size() > zz.size());
}

You can still not call this as part of a constant expression with b as false though.


As mentioned in the comments, you can make this function work (assuming it is called with arguments that are usable in a constant expression) by using string_view instead of const string& since C++17. (Requires #include<string_view>). This works because std::string_view is a literal type (in particular it has constexpr constructors) and its size function is constexpr as well.

walnut
  • 21,629
  • 4
  • 23
  • 59
  • sorry , i have two questions . first , i found a qunstion is use a not declared constexpr function in a constexpr function .https://stackoverflow.com/questions/52960040/does-all-the-functions-inside-a-constexpr-function-in-constexpr-context-must-be – Nater Jan 24 '20 at 09:30
  • @Nater I think the answer in the linked question basically says the same thing as I did. Not sure what your question is. – walnut Jan 24 '20 at 09:34
  • my previous question is why .size() function can never be called in a constant expression but a general function can be call – Nater Jan 24 '20 at 10:20
  • @Nater A call to a non-`constexpr` function can appear in a `constexpr` function's definition, but it can not be actually be called in a constant expression. That means that if the non-`constexpr` function *would* be called through the `constexpr` function, then the whole expression in which the call appears is not a constant expression. This is the same for `.size()` and for `bar()` in the question that you linked. – walnut Jan 24 '20 at 10:57
  • The problem is then that, although a call to a non-`constexpr` function can appear in a `constexpr` function, a function cannot be `constexpr` if it will *always* evaluate the non-`constexpr` call, because a `constexpr` function must be usable as constant expression for at least one set of possible arguments. This last requirement basically protects you from writing `constexpr` functions that cannot actually be used at compile-time. It is important to realize that `constexpr` means "*can sometimes be evaluated at compile-time*", not "*can always be evaluated at compile-time*". – walnut Jan 24 '20 at 10:57
0

I think the top answerin this thread can also be very helpful in answering your question.

Jon
  • 47
  • 1
  • 7