2015-05-16 45 views
0

我有这样的代码,工程已:地转换对象

// 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

我可能失去了一些东西简单,但感谢帮助。

回答

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

然后通过bind产生的func s的参数荷兰国际集团,但也留下了占位符:

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

好吧,这是有效的,但是我有点惊讶,没有一个成员函数特定形式的绑定,假设占位符,因为它似乎繁琐的不断重复....? – Brad

+0

@BitBlitz你可以写一个。这是一个非常具体的用例,它只需要绑定参数,而不是成员函数的实例,并且只有几行才能完成。 – Barry

+0

我试图写一个。我想出了一些适用于我的GCC 4.6编译器的东西,但不适用于CPP.SH.上面的问题的细节。 – Brad

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

这应该使几乎所有你需要的语法。