有没有一种通用的方法来传递需要较少工作的重载方法的指针(比我的示例) [英] Is there a generic way to pass pointers of overloaded methods that requires less work (than my example)

查看:78
本文介绍了有没有一种通用的方法来传递需要较少工作的重载方法的指针(比我的示例)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个函数,使用C ++ 17,我可以从任何对象应用任何方法:

So I have a function where, using C++17, I'm able to apply any method from any object:

#include <functional>

template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
    std::invoke(method, object, args...);
}

我要问的是:有什么方法可以改进此方法,以便在方法重载时减少函数调用者的工作.

What I ask: Is there a way to improve this to require less work for the caller of the function when the method is overloaded.

使用重载方法的示例:

#include <iostream>

class Foo
{
    int bottles;

public:

    void Edit ()
    {
        bottles = 666;
    }

    void Edit (int number)
    {
        bottles = number;
    }
    
    void Talk () const
    {
        std::cout << bottles << " bottles of beer of the wall" << std::endl;
    }
};

class Bar
{
    Foo foo;
    
    void TrickEdit (int number)
    {
        // Because Foo::Edit is overloaded, we need to do some work:
    
        using Method = void (Foo::*)(int);
    
        Method ptr = &Foo::Edit;
        
        ApplyMethod(foo, ptr, number);
    }
    
    void TrickTalk () const
    {
        // it's a lot neater when the method isn't overloaded:
    
        ApplyMethod(foo, &Foo::Talk);
    }

public:

    void Trick ()
    {
        TrickEdit(900);
        TrickTalk();    
    }   
};


int main ()
{
    Bar().Trick();
    
    return 0;
}

我正在尝试执行该功能上的工作.问题似乎在于&Foo::Edit有两个不同的位置,具体取决于我们所指的Edit.

I'm trying to perform the work at the function instead. The problem seems to lie in that &Foo::Edit has two different locations, depending on which Edit we're referring to.

C ++常见问题解答-指向成员函数的指针中Stroustrup和其他知名作家,我读到:

In C++ FAQ - Pointers to member functions by Stroustrup and other reputable authors, I read:

问题:我需要类似函数指针的东西,但具有更大的灵活性和/或线程安全性;还有另一种方法吗?

Question: I need something like function-pointers, but with more flexibility and/or thread-safety; is there another way?

答案:使用一个功能类.

Answer: Use a functionoid.

问题:什么是函数类,为什么我要使用一个?

Question: What the heck is a functionoid, and why would I use one?

答案:功能类固醇是类固醇的功能.功能类严格比功能强大,并且额外的功能解决了使用功能指针时通常面临的一些(不是全部)挑战. [...]功能类软件并不能解决制作灵活软件时遇到的所有问题,但是它们严格比功能指针更强大,并且至少值得评估.实际上,您可以轻松证明函数类没有失去对函数指针的任何控制权,因为您可以想象老式的函数指针方法等同于拥有一个global(!)函数对象.由于您始终可以创建全局功能类对象,因此您不会失去任何基础. QED.

Answer: Functionoids are functions on steroids. Functionoids are strictly more powerful than functions, and that extra power solves some (not all) of the challenges typically faced when you use function-pointers. [...] Functionoids don’t solve every problem encountered when making flexible software, but they are strictly more powerful than function-pointers and they are worth at least evaluating. In fact you can easily prove that functionoids don’t lose any power over function-pointers, since you can imagine that the old-fashioned approach of function-pointers is equivalent to having a global(!) functionoid object. Since you can always make a global functionoid object, you haven’t lost any ground. QED.

考虑到权力"是指编程的目的基本上是减少工作重复,并且使用正常功能,我们将避免在我的问题中概述的调用站点上进行额外的工作,常见问题解答答案暗示应该使用功能类来解决此问题.但是,对于我一生来说,我看不到在这种情况下函数类将如何提供帮助.

Given that the "power" of programming is basically the reduction of work duplication, and that with a normal function we would avoid the extra work at the call site that I've outlined in my problem, the FAQ answer implies that there should be a solution to this using functionoids. However, for the life of me, I can't see how functionoids would help in this case.

推荐答案

您可以编写一个变量模板,该模板指定Args...应该是什么.

You can write a variable template that specifies what Args... should be.

template <typename... Args>
struct Overload {
    template<typename R, typename O>
    operator R(O::*)(Args...) (R(O::*p)(Args...)) const { return p; }
    template<typename R, typename O>
    operator R(O::*)(Args...) const (R(O::*p)(Args...) const) const { return p; }
};

template <typename... Args>
Overload overload;

使用方式类似于

struct A
{   
    void Do() { std::cout << "Do no parm" << std::endl; }
    void Do(int) { std::cout << "Do 1 parm" << std::endl; }
    void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};  

template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
    std::invoke(method, object, args...);
}

int main()
{   
    A a;
    ApplyMethod( a, overload<>(&A::Do));
    ApplyMethod( a, overload<int>(&A::Do), 1); 
    ApplyMethod( a, overload<int, int>(&A::Do),1,2);
}

这是 Qt所做的,因为它是现代信号和插槽

This is what Qt does for it's modern signals and slots.

这篇关于有没有一种通用的方法来传递需要较少工作的重载方法的指针(比我的示例)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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