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

Convert from pointer-to-member template function to functional type objects

本文关键字:函数 转换 类型 对象 指针 成员      更新时间:2023-10-16

我已经有了这样的代码:

// 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 << " missingn";
        }
    }
};

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

我想修改map上的模板函数,使用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

我可能遗漏了一些简单的东西,但感谢你的帮助。

当您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 << " missingn";
    }    
}

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

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

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