【发布时间】:2021-01-27 08:25:32
【问题描述】:
当函数的返回值没有被实际使用时,有没有办法允许函数指针类型的模板参数接受任何(而不是特定的)返回类型的函数?这是一个 MCVE 来说明我的意思:
int returnInt(int) { return 0; }
void returnVoid(int) { }
template <int (*Func)(int)>
struct foo { void bar(int x) { Func(x); } };
int main(int, char *[]) {
foo<returnInt> a; // ok
foo<returnVoid> b; // argument of type "void (*)(int)" is incompatible
// with template parameter of type "int (*)(int)"C/C++(458)
}
我知道我可以这样做,作为一种解决方法:
template <typename ReturnType, ReturnType (*Func)(int)>
struct foo { void bar(int x) { Func(x); } };
int main(int, char *[]) {
foo<int, returnInt> a; // ok
foo<void, returnVoid> b; // ok
}
甚至这个(在我看来更糟,因为我们失去了对函数类型的参数类型的类型检查并且可能落入 SFINAE):
template <typename FuncType, FuncType *Func>
struct foo { void bar(int x) { Func(x); } };
int main(int, char *[]) {
foo<decltype(returnInt), returnInt> a; // ok
foo<decltype(returnVoid), returnVoid> b; // ok
}
但我想知道是否有一种方法可以在不添加没有其他用途的额外模板参数的情况下做到这一点。
【问题讨论】:
-
您使用的是哪个 C++ 版本?
-
@florestan Unspecified - 如果它可能符合某些特定标准(最高和/或包括 c++20),那将是一个很好的答案。 (目前我的目标是 c++17,但不要将其视为对答案的限制。)
-
C++17 为非类型模板参数提供
auto。 -
由于客户端 API 不是函数模板(或者相反,是类模板),因此很多时候答案可能是专业化,因为部分类模板专业化提供了详细的实现(/演绎)控制,同时不会弄乱客户端(模板参数)API。我添加了一个答案来展示这种方法。