从指针到成员模板函数转换为函数类型对象

时间:2015-05-16 03:09:18

标签: c++ c++11

我已经使用了这段代码:

// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <map>
using namespace std;

struct C
{
    C(int i): y_(i) {};
    int y_;
    string op1(int x)
    {
       std::ostringstream oss;
       oss << "operation 1: " << x+y_;
       return oss.str();
    }
    string op2(string x)
    {
       std::ostringstream oss;
       oss << "operation 2: " << x << "+" << y_;
       return oss.str();
    }
};

struct container: map<string, C> 
{
// doesn't compile
// void safeOperation(string key, ??? bound_function_and_arg_object )

    template< typename argType >
    void safeOperation(string key, string (C::*mf)(argType a), argType a)
    {
        iterator it = find(key);
        if (it != end())
        {
            C* pC = &(it->second);

            cout << (pC->*mf)(a) << "\n";
        }
        else
        {
            cout << "key: " << key << " missing\n";
        }
    }
};


int main () {
    container objects;

    objects.insert(container::value_type("a1", C(1)));
    objects.insert(container::value_type("b2", C(2)));
    objects.insert(container::value_type("c3", C(3)));

    objects.safeOperation("a1", &C::op1, 1);    
    objects.safeOperation("b2", &C::op1, 2);    
    objects.safeOperation("d4", &C::op1, 4);    
    objects.safeOperation("c3", &C::op2, string("3"));    

  return 0;
}

我想更改地图上的模板函数以使用std :: mem_fun并将参数与操作绑定在一起,而不是将它们指定为safeOperation的单独参数。

换句话说,我更喜欢将safeOperation称为:

// wrong, but hopefully communicates what I'm trying to do:
objects.safeOperation(someKey, bind(&C::op1, 4)); 

示例代码在此处:http://cpp.sh/74pgb

我可能错过了一些简单的东西,但感谢帮助。

2 个答案:

答案 0 :(得分:1)

boost/std::bind创建一个具有特定于实现的类型的对象。唯一的要求是使用operator()可以调用对象。

要处理任何功能对象,您可以通过以下方式更改功能模板:

template< typename F >
void safeOperation(string key, F f)
{
    // ...
        cout << f(pC) << "\n";

// ...
objects.safeOperation("someKey", bind(&C::op1, placeholders::_1, 4)); 

这应该可以启用几乎所需的语法。

答案 1 :(得分:1)

当你bind成员函数时,第一个参数必须是其成员函数的类的实例。所以你要做的是概括safeOperation以获取可以在C*上调用的任何函数:

template< typename F >
void safeOperation(string key, F func) {
    iterator it = find(key);
    if (it != end())
    {
        C* pC = &(it->second);

        cout << func(pC) << "\n";
    }
    else
    {
        cout << "key: " << key << " missing\n";
    }    
}

然后通过func使用参数生成bind s,但也留下占位符:

using namespace std:;placeholders;
objects.safeOperation("a1", std::bind(&C::op1, _1, 1));
//                                             ^^
//                                    placeholder for pC