重载函数作为可变模板函数的参数 [英] Overloaded function as argument of variadic template function

查看:164
本文介绍了重载函数作为可变模板函数的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用variadic模板函数,它接受参数重载函数及其参数:

I'm trying to make variadic template function, which takes as arguments overloaded function and its arguments :)

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...); }

我想调用 doit 模板说明符或类型:

I want to call doit without any template specifiers nor casting:

cout << doit(sumall, 7, 6) << endl

这不会编译,但是当返回类型为void时,一切运行正常:

That doesn't compile, but when return types are void, everything work perfect:

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);

是否可以修改第一个模板只使用modyfing doit 模板(我想保留 sumall 函数和 doit 调用)?我认为可以通过删除 typename R ,只保留 template< typename ... A> c $ c> R 取决于 A ... f

Is it possible to modify first template to work with modyfing only doit template (I want to preserve sumall functions and doit call)? I think it can be done with removing typename R and leaving just template<typename... A> since R depends on A... and f, but I don't have any idea how to show that dependency.

推荐答案

当获取函数的指针时,编译器需要知道哪个您要使用的重载。没有办法传递一个指针到一个重载集,并让编译器决定以后。我没有你的示例工作与我尝试的任何编译器(非常新版本的EDG,gcc和clang)。

When taking a pointer of a function the compiler needs to know which of the overloads you want to use. There is no way to pass a pointer to an "overload set" and have the compiler decide later. Neither of you examples works with any of the compilers I tried (very recent versions of EDG, gcc, and clang).

我不认为你可以做你希望不改变您的呼叫的符号。如果你愿意改变调用,你可以把关于被调用的函数的知识封装到一个类中,例如:

I don't think you can do what you want without changing the notation of your call. If you are willing to change the call you can encapsulate the knowledge about the function to be called into a class, e.g.:

struct sumall_t {
    template <typename... T>
    auto operator()(T... args) -> decltype(sumall(args...)) {
        return sumall(args...);
    }
};

这有效地创建了一个重载集合的包装器。由于结果类型不能直接推导,并且可能取决于函数的调用方式,因此您需要使用不同版本的 doit()

This effectively creates a wrapper for an overload set. Since the result type can't be deduced directly and may depend on how the function is called, you'd need to use a different version of doit() as well:

template<typename Func, typename... A>
auto doit( Func f, A... a) ->decltype(f(a...)) {
    return f(a...);
}

这样会用到这样:

doit(sumall_t(), 1, 2);

另一种解决方法是强制指定结果类型:两个东西一次:你想推断要调用的函数的结果类型,并且希望指导编译器选择一个特定的结果集的重载。然而,这些是相互依存的。如果从函数指针中删除任何模板的依赖,你不需要包装重载集,因为你可以从函数的第一个参数中确定重载函数的选择。如果你声称我的编译器可以做到,如果返回类型不是 void 我会说,你的编译器实际上是错误的这样做。

Another way to fix this is to mandate specification of the result type: in some way you try to do two things at once: you want to deduce the result type of the function to be called and you want to guide the compiler to choose a specific overload of a result set. However, these are interdependent. If you remove any dependency on deducing any template from the function pointer, you don't need wrap the overload set because you can determine the choice of overloaded function from the first argument to the function. In case you claim that "my compiler can do it if the return type isn't void" I'd say that your compiler is actually wrong in doing this.

这篇关于重载函数作为可变模板函数的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆