繁体   English   中英

std ::成员函数指针的映射?

[英]std::map of member function pointers?

我需要用<std::string, fn_ptr>对实现一个std::map 函数指针是指向拥有映射的同一类的方法的指针。 我们的想法是直接访问方法,而不是实现交换机或等效方法。

(我使用std::string作为地图的键)

我对C ++很陌生,所以有人会发布一些伪代码或链接来讨论用函数指针实现一个映射吗? (指向拥有地图的同一个类所拥有的方法的指针)

如果您认为我的问题有更好的方法,也欢迎提出建议。

这是我能想到的最简单的事情。 注意没有错误检查,并且地图可能有用地变为静态。

#include <map>
#include <iostream>
#include <string>
using namespace std;

struct A {
    typedef int (A::*MFP)(int);
    std::map <string, MFP> fmap;

    int f( int x ) { return x + 1; }
    int g( int x ) { return x + 2; }


    A() {
        fmap.insert( std::make_pair( "f", &A::f ));
        fmap.insert( std::make_pair( "g", &A::g ));
    }

    int Call( const string & s, int x ) {
        MFP fp = fmap[s];
        return (this->*fp)(x);
    }
};

int main() {
    A a;
    cout << a.Call( "f", 0 ) << endl;
    cout << a.Call( "g", 0 ) << endl;
}

模板实现可能如下所示:

class Factory {
public:
    enum which {
        foo, bar, baz
    };

    template<which w>
    A* newA(...);
    ...
};
template<Factory::which w>
A* Factory::newA(...) {
    /* default implementation */
    throw invalid_argument();
}
template<>
A* Factory::newA<Factory::foo>(...) {
    /* specialization for a 'foo' style A */
    ...
}
....

这要求在编译时用于确定调用哪个newA的值是已知的。 您可以使用const char *作为模板参数,但不能保证它可以在所有编译器上运行。

另一种选择是创建辅助工厂,每个工厂创建方法一个,并将它们存储在地图中。 这不是存储方法指针的一个巨大优势,但是它允许您定义默认创建方法并简化从地图中获取内容(不需要检查密钥是否存在,因为您将获得默认工厂)。 在缺点方面,每个未知密钥的条目将添加到地图中。

此外,如果您为密钥类型使用enum而不是字符串,则无需担心检查映射中是否存在密钥。 虽然有人可能会将无效的enum密钥传递给newA ,但他们必须明确地转换参数,这意味着他们不会意外地执行此操作。 我很难想象有人会故意在newA造成崩溃; 潜在的场景涉及安全性,但应用程序员可能会在不使用您的类的情况下使应用程序崩溃。

另一个选择是使用委托作为函数指针的反对者。 这个委托实现非常快,支持多态性,并且可以很好地与stl容器配合使用。 你可以有类似的东西:

class MyClass {
public:
    // defines
    typedef fastdelegate::FastDelegate2<int, int, int> MyDelegate;
    typedef std::map<std::string, MyDelegate> MyMap;

    // populate your map of delegates
    MyClass() {
        _myMap["plus"] = fastdelegate::MakeDelegate(this, &Plus);
        _myMap["minus"] = fastdelegate::MakeDelegate(this, &Minus);
    }

    bool Do(const std::string& operation, int a, int b, int& res){
        MyMap::const_iterator it = _myMap.find(operation);
        if (it != _myMap.end()){
            res = it.second(a,b);
            return true;
        }

        return false; 
    }
private:
    int Plus (int a, int b) { return a+b; }
    int Minus(int a, int b) { return a-b; }
    MyMap _myMap;    
};      

从C ++ 14开始,我们可以使用泛型lambda轻松摆脱成员方法的指针。
它遵循一个由通用lambda函数组成的前向函数的最小工作示例:

#include<utility>
#include<map>
#include<string>
#include<iostream>

struct SomeClass { };
struct SomeOtherClass { };

struct Test {
    void test(SomeClass) { std::cout << "SomeClass" << std::endl; }
    void test(SomeOtherClass) { std::cout << "SomeOtherClass" << std::endl; }
};

int main() {
    Test test;

    auto l = [&test](auto c){ test.test(c); };
    std::map<std::string, decltype(l)> m;

    m.emplace("foo", l);
    m.emplace("bar", l);

    m.at("foo")(SomeClass{});
    m.at("bar")(SomeOtherClass{});
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM