Явное указание class не работает для параметра-класса

Почему этот код не компилируется, хотя я явно указал, что передавать надо класс?

#include <concepts>
#include <type_traits>

template<class T>
concept Class = std::is_class_v<T>;

class A {

};

template<Class A>
void foo() {
    class A a;
}

int main(){
    foo<A>();
}

Ответы (2 шт):

Автор решения: Harry

Попробуйте так:

template<class T>
concept Class = std::is_class_v<T>;

template<Class A>
void foo() {
    A a;
}

class A {
};

int main(){
    foo<A>();
}

Странная у вас конструкция, однако -

class A a;

Update

Короче, если вам нужен в foo() объект класса A, который объявлен вне функции - пишите

template<Class B>
void foo() {
    class A a;
}

Если уж совсем не можете без этого class обходиться.

Если нужен объект именно того A, которое является параметром шаблона - то

template<Class A>
void foo() {
    A a;
}

Если хотите так, чтоб нарушить правила языка и компилировалось - то тогда придумывайте самостоятельно...

→ Ссылка
Автор решения: HolyBlackCat

Похоже, что внутри шаблона его шаблонные параметры-типы обрабатываются точно так же, как псевдонимы типов, созданные с помощью typedef или using. Стандарт называет их typedef-name.

[temp.param]/3

A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared without template) ...

Значит, ваш код не работает по той же причине, что и:

class A {};
using B = A;
class B b;

Справа от class может быть написано только настоящее имя класса, а не ссылающийся на него псевдоним.

[dcl.type.elab]/2

... If the identifier ... resolves to a typedef-name ..., the elaborated-type-specifier is ill-formed. ...

Здесь elaborated-type-specifier - это конструкция вида class ИмяТипа (вместо class может быть struct,enum,...). А под identifier имеется в виду как раз ИмяТипа, написанное справа от class.

→ Ссылка