在以下代码中:
template<auto A>
struct S{};
template<template <auto A> class H>
auto foo(){
return A;
}
auto bar(){
return foo<S<1>>(); // should return 1
}
我希望它会编译一个只返回1
的bar()方法。
但是我得到这些错误:
<source>: In function 'auto foo()':
<source>:15:12: error: 'A' was not declared in this scope
15 | return A;
| ^
<source>: In function 'void bar()':
<source>:19:15: error: no matching function for call to 'foo<S<1> >()'
19 | foo<S<1>>();
| ^
<source>:14:6: note: candidate: 'template<template<auto A> class H> auto foo()'
14 | auto foo(){
| ^~~
<source>:14:6: note: template argument deduction/substitution failed:
有什么方法可以实际获得值A?
答案 0 :(得分:3)
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
的模板参数是一种类型(不是模板)。然后,将该类型作为参数提供给助手,并与模板专门化进行匹配。由于该类型已填充参数,因此专业化将其提取并返回。
答案 1 :(得分:1)
template<template <auto A> class H>
auto foo(){
return A;
}
定义一个采用模板而不是专门化的函数。这意味着您需要像foo<S>()
那样称呼它,因为S
是一个模板,而不是foo<S<1>>()
,因为S<1>
是一个专业。
您可以做的一件事是将foo
更改为
template<template <auto> class H, auto A>
auto foo(){
return A;
}
然后您可以像使用它
foo<S, 1>()
然后让foo使用模板S
并具有要使用的值(在这种情况下为1)。
如果您希望foo<S<1>>()
返回1
,则可以添加一个辅助函数并将foo
更改为以下内容
template<template <auto> class T, auto V>
constexpr auto get_value(T<V>)
{
return V;
}
template<typename T>
auto foo(){
return get_value(T{});
}
答案 2 :(得分:0)
我认为您可能想要这样的东西:
#include <iostream>
template<auto A_val>
struct S {
static constexpr auto A = A_val;
static constexpr auto v = 2;
};
template<class H>
auto foo(){
return H::A;
}
auto bar(){
return foo<S<1>>();
}
int main()
{
std::cout << bar() << std::endl; // Prints "1"
return 0;
}