2012-04-07 2 views
5

я считаю следующее, чтобы быть самым дешевым способом связывания локальной переменной закрытия:самый дешевый способ связывания локальной переменной закрытия

void ByRValueReference(A&& a) { 
} 

std::function<void()> CreateClosureByRValueReference() { 
    A a; 
    std::function<void()> f = std::bind(&ByRValueReference, std::move(a)); // !!! 
    return f; 
} 

Однако, он не компилируется под Clang 3.1:

error: no viable conversion from '__bind<void (*)(A &&), A>' to 'std::function<void()>' 

и gcc 4.6.1:

/usr/include/c++/4.6/functional:1778:2: error: no match for call to ‘(std::_Bind<void (*(A))(A&&)>)()’ 

Я нарушаю стандарт или просто разбитые стандартные библиотеки?

+1

Я думаю, что его 'функция '. – RedX

+2

На самом деле, это немного дорого стоит здесь: 'std :: function'. Если вы действительно заботитесь об эффективности, я бы возвращал 'decltype (std :: bind (...))' – pmr

ответ

3

Это по дизайну std::bind. Полная спецификация в 20.8.9.1.2 Функция шаблона привязки [func.bind.bind], но в этом случае последняя пуля пункта 10 (который описывает, как используются связанные параметры) применяется:

- в противном случае , значение tid и ее тип Vi является TiD cv &

Итак, другими словами, std::move(a) приведет к обертке вызова запоминания A (от конструкции перемещения), а затем, когда operator() используется этот элемент будет направлен как lvalue (с дополнительными cv-квалификаторы, соответствующие cv-квалификаторам оболочки вызова, но я отвлекаюсь). Хотя он был принят как rvalue.

Такое несоответствие может быть решена с помощью лямбда:

std::bind([](A& a) { ByRValueReference(std::move(a)); }, std::move(a)) 

Это можно утверждать, что это более ясно, что дальнейшие вызовы в результате вызова завернутые сомнительны (поскольку A член обязан был переместился с), но я не слишком люблю поведение std::bind в целом.

+0

Если вы идете с лямбдой, вы можете также вернуть '[& a]() {...}' напрямую и сохранить привязку ... –

+0

@KerrekSB Это имеет разную семантику, чем вызов 'std :: bind' и в случае OP приведет к UB. –

+0

О, я вижу, действительно. Благодарю. –

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