Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++20 not support "void f(Concept const auto&)"?

#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&)"?

like image 643
xmllmx Avatar asked Apr 09 '20 09:04

xmllmx


2 Answers

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.

like image 81
walnut Avatar answered Oct 17 '22 09:10

walnut


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 (or decltype(auto)) being constrained is always immediately preceded by the constraint.

like image 23
metalfox Avatar answered Oct 17 '22 10:10

metalfox