为什么C++20不支持"void f(Concept const auto&)"?

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);
}

使用 clang++ -std=c++20 -stdlib=libc++ z.cpp 编译,错误消息为:

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.

为什么C++20不支持"void f(Concept const auto&)"?

概念名称必须出现在 auto 之前。或者:

void f(const Concept auto&)

或:

void f(Concept auto const&)

都有效。

动机是 (P1141):

To keep things simple, an auto (or decltype(auto)) being constrained is always immediately preceded by the constraint.

你的语法有误。

type-constraints,比如这里的概念HasSize,直接属于placeholder-type-specifier之前,即在 autodecltype(auto):

之前
void f6(const HasSize auto& arg) {}

参见 C++20 草案的 [dcl.spec.auto]

cv-qualifiers,例如const,与placeholder-type-specifiers是分开的,参见 [decl.type]/1


正如@super 在问题评论中提到的,函数参数中不允许 decltype(auto)。所以这似乎是一个接受它的 Clang 错误,请参阅 [dcl.spec.auto]/2 它只允许 auto 案例用于 placeholder-type-specifier 在函数参数中。