A
не обозначает то, что существует. Параметр foo
представляет собой шаблон , а не специализацию. Важно провести различие, потому что именно поэтому вы получаете ошибку несоответствия при передаче S<1>
, правильный аргумент написанного вами будет foo<S>
.
S<1>
- это специализация, в ней заполнен пропущенный бит (аргумент). Но H
- это не специализация, это сам шаблон, без аргумента. A
нет ничего, кроме мнемоники для чего-то для заполнения , это еще не то, что там, так что вы не можете использовать это.
Чтобы получить то, что вы хотите, потребуется частичная специализация шаблона. Это не применимо к шаблонам функций, но мы можем обойти это, перенаправив к члену шаблона класса. Примерно так:
template<auto A>
struct S{};
template<typename> struct foo_helper;
template<template <auto> class H, auto A>
struct foo_helper<H<A>> {
static auto run() { return A; }
};
template<class H>
auto foo(){
return foo_helper<H>::run();
}
auto bar(){
return foo<S<1>>(); // should return 1
}
Теперь параметр шаблона foo
является типом (не шаблоном). Затем этот тип передается в качестве аргумента помощнику и сопоставляется со специализацией шаблона. Поскольку тип имеет аргумент заполненный, специализация извлекает его и возвращает его.