krd*_*dln 7 c++ variadic-functions variadic-templates c++11
我正在尝试创建可变参数模板函数,它将参数作为重载函数及其参数:)
int sumall(int a) { return a; }
int sumall(int a, int b) { return a+b; }
template<typename R, typename... A>
R doit( R(*f)(A...), A... a) {
return f(a...); }
Run Code Online (Sandbox Code Playgroud)
我想调用doit
没有任何模板说明符或转换:
cout << doit(sumall, 7, 6) << endl
Run Code Online (Sandbox Code Playgroud)
这不会编译,但当返回类型无效时,一切都很完美:
void printsum(int a) { cout << a << endl; }
void printsum(int a, int b) { cout << a+b << endl; }
template<typename... A>
void vdoit( void(*f)(A...), A... a) {
f(a...); }
// ...
vdoit(printsum, 7, 6);
Run Code Online (Sandbox Code Playgroud)
是否可以修改第一个模板以使用仅限modyfing doit
模板(我想保留sumall
函数和doit
调用)?我认为可以通过删除typename R
和离开来完成,template<typename... A>
因为R
依赖A...
和f
,但我不知道如何显示依赖.
在获取函数的指针时,编译器需要知道您要使用哪个重载.没有办法将指针传递给"重载集"并让编译器稍后决定.你们两个例子都不适用于我尝试的任何编译器(最新版本的EDG,gcc和clang).
我不认为你可以做你想做的事而不改变你的电话记号.如果您愿意更改调用,可以将有关要调用的函数的知识封装到类中,例如:
struct sumall_t {
template <typename... T>
auto operator()(T... args) -> decltype(sumall(args...)) {
return sumall(args...);
}
};
Run Code Online (Sandbox Code Playgroud)
这有效地为过载集创建了一个包装器.由于结果类型不能直接推导出来并且可能取决于函数的调用方式,因此您还需要使用不同的版本doit()
:
template<typename Func, typename... A>
auto doit( Func f, A... a) ->decltype(f(a...)) {
return f(a...);
}
Run Code Online (Sandbox Code Playgroud)
然后使用这样的东西:
doit(sumall_t(), 1, 2);
Run Code Online (Sandbox Code Playgroud)
修复此问题的另一种方法是强制要求结果类型的规范:在某种程度上,您尝试同时执行两项操作:您希望推导出要调用的函数的结果类型,并且您希望引导编译器选择特定的结果集的重载.但是,这些是相互依存的.如果从函数指针中删除对推导任何模板的任何依赖性,则不需要包装重载集,因为您可以确定从第一个参数到函数的重载函数的选择.如果您声称"如果返回类型不是我的编译器可以执行此操作void
",我会说您的编译器在执行此操作时实际上是错误的.
归档时间: |
|
查看次数: |
1729 次 |
最近记录: |