2013-04-23 2 views
9

Я играл в arround с помощью std :: function и std :: bind, и я заметил что-то неинтуитивное, и я хотел бы лучше понять его.Понимание std :: function и std :: bind

Например:

void fun() 
{ 
} 

void hun(std::string) 
{ 
} 

int main() 
{ 

    function<void(int)> g = &fun; //This fails as it should in my understanding. 

    function<void(int)> f = std::bind(fun); //This works for reasons unknown to me  
    function<void(int, std::string)> h = std::bind(hun); //this doesn't work 

return 0; 
} 

Как можно связать function<void(int)> к функции, которая является недействительным(). Тогда я мог бы позвонить f (1) и получить удовольствие(). Я хотел бы понять, как это делается. В результате внедрения этой Microsoft Visual Studio 2012 меня потеряли в море нечитаемых макросов. поэтому я задаю этот вопрос здесь.

+0

Я использую vs2012 Express edition. – Alex

+0

вы можете порекомендовать такой сайт? – Alex

+0

Компиляция с _clang_ и _g ++ _ обоими. +1, интересная ситуация. – soon

ответ

7

Если вы не используете разделители аргументов (_1, _2, ...), то любые аргументы, переданные объекту функции, возвращаемому с std::bind, будут просто отброшены. С:

std::function<void(int)> f = std::bind(fun, std::placeholders::_1); 

Я получаю (длинную и уродливую) ошибку, как ожидалось.

Для людей, заинтересованных в Standardese:

§20.8.9.1.2 [func.bind.bind]

template<class F, class... BoundArgs> 
*unspecified* bind(F&& f, BoundArgs&&... bound_args); 

p3 Возвращает: переадресация вызова оболочки g со слабым типом результата (20.8.2). Эффект g(u1, u2, ..., uM) должен быть INVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type), где резюме представляет CV -qualifiers из gи значения и типы аргументов, связанных v1, v2, ..., vN определяются, как указано ниже.

р10 Значение связанных аргументов v1, v2, ..., vN и их соответствующих типов V1, V2, ..., VNзависят от типов TiD, полученных из вызова bind и резюме -qualifiers резюме обертки вызова g следующим образом:

  • , если это TiDreference_wrapper<T>, аргумент tid.get() и его тип Vi является T&;
  • если значение is_bind_expression<TiD>::value равно true, аргумент tid(std::forward<Uj>(uj)...) и его тип Vi - result_of<TiD cv (Uj...)>::type;
  • если значение j из is_placeholder<TiD>::value не равен нулю, то аргумент std::forward<Uj>(uj) и его тип Vi является Uj&&;
  • в противном случае это значение tid и его тип Vi is TiD cv &.
+0

Кроме того, даже если std :: function f = std :: bind (fun); компилирует. На самом деле невозможно называть f: f(); не удается скомпилировать. –

+1

@PeterR: Очевидно, потому что подпись 'f' задает один аргумент. :) – Xeo

6

Переадресация вызова обертка порождена вызов функции шаблона bind может принимать любое количество дополнительных параметров; они будут проигнорированы. Эффективная арность и минимальная сигнатура выражения bind определяются используемым в его конструкции placeholder, и к каким вызываемым аргументам они привязаны.

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