#include <string>
template<typename T>
concept HasSize = requires(T obj)
{
obj.size();
};
void f1(HasSize auto arg) {} // ok
void f2(HasSize auto&& arg) {} // ok
void f3(HasSize decltype(auto) arg) {} // ok
void f4(HasSize auto& arg) {} // ok
void f5(HasSize auto* arg) {} // ok
void f6(HasSize const auto& arg) {} // error
int main()
{
std::string str{};
f1(std::string{});
f2(std::string{});
f3(std::string{});
f4(str);
f5(&str);
f6(str);
}
Compiled with clang++ -std=c++20 -stdlib=libc++ z.cpp
and the error messages are:
z.cpp:15:6: error: variable has incomplete type 'void'
void f6(HasSize const auto& arg) {} // error
^
z.cpp:15:9: error: too few template arguments for concept 'HasSize'
void f6(HasSize const auto& arg) {} // error
^
z.cpp:4:9: note: template is declared here
concept HasSize = requires(T obj)
^
z.cpp:15:33: error: expected ';' after top level declarator
void f6(HasSize const auto& arg) {} // error
^
;
3 errors generated.
Why does C++20 not support "void f(Concept const auto&)"?
You have the syntax wrong.
type-constraints, such as the concept HasSize
here, belong directly before the placeholder-type-specifier, i.e. before auto
or decltype(auto)
:
void f6(const HasSize auto& arg) {}
See [dcl.spec.auto] of the C++20 draft.
The cv-qualifiers, such as const
, are separate from the placeholder-type-specifiers, see [decl.type]/1.
As mentioned by @super in a question comment decltype(auto)
is not allowed in a function parameter. So this seems to be a Clang bug to accept it, see [dcl.spec.auto]/2 which only allows the auto case for a placeholder-type-specifier in a function parameter.
The concept name must appear right before auto
. Either:
void f(const Concept auto&)
or:
void f(Concept auto const&)
are both valid.
The motivation was (P1141):
To keep things simple, an
auto
(ordecltype(auto)
) being constrained is always immediately preceded by the constraint.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With