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.