2014-10-03 2 views
1

Возможно, кто-то поможет объяснить, почему я получаю сообщение об ошибке при компиляции следующего кода с помощью Xcode 5.1 в OS X. Apple LLVM version 5.1 (clang-503.0.40) (на основе на LLVM 3.4svn).Ошибка компилятора при конструировании вектора std :: function

#include <vector> 
#include <functional> 

void func1(const std::string& value) 
{ 
    // ... 
} 

void func2(const std::string& value, int min, int max) 
{ 
    // ... 
} 

class X 
{ 
public: 
    void x1(const std::string& value) 
    { 
     // ... 
    } 

    void x2(const std::string& value, int min, int max) 
    { 
     // ... 
    } 
}; 

const std::vector<std::function<void(std::string)>> functions 
{ 
    func1, 
    std::bind(func2, std::placeholders::_1, 5, 6), 
    std::mem_fn(&X::x1),        // compiler error 
}; 

сообщила об ошибке:

no matching constructor for initialization of 'const std::vector<std::function<void (std::string)> >' 
const std::vector<std::function<void(std::string)>> functions 

Кроме того, я хотел бы добавить X :: x2 вектору. Как мне это сделать?

Спасибо.

+4

функции-члены нужен объект для работы на их подписи не совместим с 'void (std :: string)' в вашем случае. Возможно, вы сможете использовать bind, чтобы он работал, но вам понадобится экземпляр. – Mat

+0

@Mat Пожалуйста, добавьте это как ответ. – balajeerc

+0

@Mat Пожалуйста, вы можете уточнить. – ksl

ответ

1

Что std::mem_fn делает, он возвращает некоторые неопределенные объектов вызываемый с дополнительным первого аргументом указателем или ссылочным типа (или даже смартом типа указателя) таким же, как тип, который функция члена или переменного членом, который передается in принадлежит (все остальные аргументы пересылаются). Это означает, что вы можете сохранить этот объект в функции оболочки, как показано ниже:

std::function<void(X*,const std::string&)> f = std::mem_fn(&X::x1); 

, а затем вызвать его с фактическим аргументом:

X x{}; 
f(&x, "foo"); // or std::mem_fn(&X::x1)(&x, "foo"); 

, который так же, как:

(&x)->x1("foo"); 

В другими словами, это скорее всего не то, что вы хотели, сохранив этот вызываемый объект в std::vectorstd::function<void(const std::string&)>. Вместо того чтобы добавлять дополнительный первый аргумент, вы должны скорее связать его с контекстом, для которого эта функция будет вызываться:

X x{}; // object in context of which the function will be called 

const std::vector<std::function<void(std::string)>> functions 
{ 
    func1, 
    std::bind(func2, std::placeholders::_1, 5, 6), 
    std::bind(&X::x1, &x, std::placeholders::_1), 
// ~~~~~~~~^ ~~~~~^ ~^   ~~~~~~~~~~^ 
//  bind function with object x and actual argument to be forwarded 
}; 

DEMO

+0

Большое спасибо. – ksl

Смежные вопросы