"no matching function for call to" 当有一个带有模板参数的函数指针作为模板参数时
"no matching function for call to" when having a function pointer with template arguments as a template argument
我正在编写一个模板包装函数,它可以应用于具有不同 number/types 个参数的函数。
我有一些有效的代码,但我正在尝试将更多参数更改为模板参数。
工作代码:
#include <iostream>
int func0(bool b) { return b ? 1 : 2; }
//There is a few more funcX...
template<typename ...ARGS>
int wrapper(int (*func)(ARGS...), ARGS... args) { return (*func)(args...) * 10; }
int wrappedFunc0(bool b) { return wrapper<bool>(func0, b); }
int main()
{
std::cout << wrappedFunc0(true) << std::endl;
return 0;
}
现在我希望 int (*func)(ARGS...)
也成为模板参数。 (这是出于性能原因。我希望将指针返回到包装器中,因为我使用它的方式会阻止编译器对其进行优化。)
这是我想出的(唯一的区别是我将一个参数更改为模板参数。):
#include <iostream>
int func0(bool b) { return b ? 1 : 2; }
//There is a few more funcX...
template<typename ...ARGS, int (*FUNC)(ARGS...)>
int wrapper(ARGS... args) { return (*FUNC)(args...) * 10; }
int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
int main()
{
std::cout << wrappedFunc0(true) << std::endl;
return 0;
}
这无法编译。它显示:
<source>: In function 'int wrappedFunc0(bool)':
<source>:9:55: error: no matching function for call to 'wrapper<bool, func0>(bool&)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:7:5: note: candidate: 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
7 | int wrapper(ARGS... args) { return (*FUNC)(args...) * 10; }
| ^~~~~~~
<source>:7:5: note: template argument deduction/substitution failed:
<source>:9:55: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:9:55: note: expected a type, got 'func0'
ASM generation compiler returned: 1
<source>: In function 'int wrappedFunc0(bool)':
<source>:9:55: error: no matching function for call to 'wrapper<bool, func0>(bool&)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:7:5: note: candidate: 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
7 | int wrapper(ARGS... args) { return (*FUNC)(args...) * 10; }
| ^~~~~~~
<source>:7:5: note: template argument deduction/substitution failed:
<source>:9:55: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:9:55: note: expected a type, got 'func0'
Execution build compiler returned: 1
(link to the compiler explorer)
在我看来这似乎是编译器的问题,但 GCC 和 Clang 都同意这一点,所以也许不是。
无论如何,如何使用指向函数的模板指针正确编译此模板?
编辑:
解决重复标志
我认为该问题的核心问题与我的问题相同,但是,它缺少允许将指针作为模板参数传递给函数(不仅是其类型)的解决方案。
这不起作用,因为一个包参数(包括 ...
的那个)消耗了所有剩余的参数。它后面的所有参数都不能明确指定,必须推导。
通常你会像这样写这样的包装器:
template <typename F, typename ...P>
int wrapper(F &&func, P &&... params)
{
return std::forward<F>(func)(std::forward<P>(params)...) * 10;
}
(如果函数在包装器内被多次调用,除最后一次调用之外的所有调用都不能使用 std::forward
。)
这将通过引用传递函数,这应该与使用函数指针完全相同,但我没有理由相信它会阻止编译器对其进行优化。
您可以通过传递 std::integral_constant<decltype(&func0), func0>{}
而不是 func0
来强制将函数编码到模板参数中,但同样,我认为它不会改变任何东西。
第二个代码段 无效 因为:
a type parameter pack cannot be expanded in its own parameter clause.
从[temp.param]/17开始:
If a template-parameter is a type-parameter with an ellipsis prior to its optional identifier or is a parameter-declaration that declares a pack ([dcl.fct]), then the template-parameter is a template parameter pack. A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded packs is a pack expansion. ... A template parameter pack that is a pack expansion shall not expand a template parameter pack declared in the same template-parameter-list.
因此请考虑以下无效示例:
template<typename... Ts, Ts... vals> struct mytuple {}; //invalid
上面的例子无效,因为模板类型参数包Ts
不能在自己的参数列表中展开
出于同样的原因,您的代码示例无效。例如,msvc.
中第二个代码段的简化版本 doesn't compile
我正在编写一个模板包装函数,它可以应用于具有不同 number/types 个参数的函数。 我有一些有效的代码,但我正在尝试将更多参数更改为模板参数。
工作代码:
#include <iostream>
int func0(bool b) { return b ? 1 : 2; }
//There is a few more funcX...
template<typename ...ARGS>
int wrapper(int (*func)(ARGS...), ARGS... args) { return (*func)(args...) * 10; }
int wrappedFunc0(bool b) { return wrapper<bool>(func0, b); }
int main()
{
std::cout << wrappedFunc0(true) << std::endl;
return 0;
}
现在我希望 int (*func)(ARGS...)
也成为模板参数。 (这是出于性能原因。我希望将指针返回到包装器中,因为我使用它的方式会阻止编译器对其进行优化。)
这是我想出的(唯一的区别是我将一个参数更改为模板参数。):
#include <iostream>
int func0(bool b) { return b ? 1 : 2; }
//There is a few more funcX...
template<typename ...ARGS, int (*FUNC)(ARGS...)>
int wrapper(ARGS... args) { return (*FUNC)(args...) * 10; }
int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
int main()
{
std::cout << wrappedFunc0(true) << std::endl;
return 0;
}
这无法编译。它显示:
<source>: In function 'int wrappedFunc0(bool)':
<source>:9:55: error: no matching function for call to 'wrapper<bool, func0>(bool&)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:7:5: note: candidate: 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
7 | int wrapper(ARGS... args) { return (*FUNC)(args...) * 10; }
| ^~~~~~~
<source>:7:5: note: template argument deduction/substitution failed:
<source>:9:55: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:9:55: note: expected a type, got 'func0'
ASM generation compiler returned: 1
<source>: In function 'int wrappedFunc0(bool)':
<source>:9:55: error: no matching function for call to 'wrapper<bool, func0>(bool&)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:7:5: note: candidate: 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
7 | int wrapper(ARGS... args) { return (*FUNC)(args...) * 10; }
| ^~~~~~~
<source>:7:5: note: template argument deduction/substitution failed:
<source>:9:55: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... ARGS, int (* FUNC)(ARGS ...)> int wrapper(ARGS ...)'
9 | int wrappedFunc0(bool b) { return wrapper<bool, func0>(b); }
| ~~~~~~~~~~~~~~~~~~~~^~~
<source>:9:55: note: expected a type, got 'func0'
Execution build compiler returned: 1
(link to the compiler explorer)
在我看来这似乎是编译器的问题,但 GCC 和 Clang 都同意这一点,所以也许不是。
无论如何,如何使用指向函数的模板指针正确编译此模板?
编辑:
解决重复标志
这不起作用,因为一个包参数(包括 ...
的那个)消耗了所有剩余的参数。它后面的所有参数都不能明确指定,必须推导。
通常你会像这样写这样的包装器:
template <typename F, typename ...P>
int wrapper(F &&func, P &&... params)
{
return std::forward<F>(func)(std::forward<P>(params)...) * 10;
}
(如果函数在包装器内被多次调用,除最后一次调用之外的所有调用都不能使用 std::forward
。)
这将通过引用传递函数,这应该与使用函数指针完全相同,但我没有理由相信它会阻止编译器对其进行优化。
您可以通过传递 std::integral_constant<decltype(&func0), func0>{}
而不是 func0
来强制将函数编码到模板参数中,但同样,我认为它不会改变任何东西。
第二个代码段 无效 因为:
a type parameter pack cannot be expanded in its own parameter clause.
从[temp.param]/17开始:
If a template-parameter is a type-parameter with an ellipsis prior to its optional identifier or is a parameter-declaration that declares a pack ([dcl.fct]), then the template-parameter is a template parameter pack. A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded packs is a pack expansion. ... A template parameter pack that is a pack expansion shall not expand a template parameter pack declared in the same template-parameter-list.
因此请考虑以下无效示例:
template<typename... Ts, Ts... vals> struct mytuple {}; //invalid
上面的例子无效,因为模板类型参数包Ts
不能在自己的参数列表中展开
出于同样的原因,您的代码示例无效。例如,msvc.
中第二个代码段的简化版本 doesn't compile