Я думаю, что ответ - нет. Это из-за разницы между std :: function и возвращаемым значением std :: bind.
- Сигнатура функции std :: function должна быть указана при объявлении.
- Сигнатура функтора, возвращаемая std :: bind, на самом деле имеет переменные аргументы шаблона, которые не будут определены, пока не будет вызван его оператор (). Это означает, что подпись не уникальна при объявлении времени, что определенно предшествует оценке времени.
Посмотрите на ожидаемый вызов, std::function<void(...)> func = postbind(strand, std::bind(foo, myfoo(), 'a', _1);
. На самом деле, компилятор знает только связанные аргументы и некоторые заполнители. Через некоторое время вызывается его оператор (), затем несвязанные аргументы заменят заполнители, и теперь компилятор может проверить, соответствуют ли все аргументы сигнатуре функции.
Если приведенные выше предложения слишком сложны для понимания, пожалуйста, позвольте мне показать код:
void foo(int) {}
foo(1); // Correct.
foo(1, 2); // Illegal, signature mismatched.
auto f = std::bind(foo, _1); // Here f has no idea about unbound args for foo.
f(1); // OK, 1 matches int.
f(1, 2); // OK too, although 2 is used.
f(1, 1, 1); // Same as before ones.
auto func = postbind(
strand, std::bind(foo, _1)); // If this is acceptable,
func(99); // this is a correct invocation then.
func(99, 98); // And this should also be happy for compiler. Ambiguity!
В результате вы должны явно указать подпись при связывании.
Но в любом случае, вот фрагмент кода, который, я думаю, может быть заменой:
template <typename... ArgTypes>
void do_post(strand_ptr strand, ArgTypes&&... args)
{
strand->post(std::bind(std::forward<ArgTypes>(args)...));
}
int main()
{
// some code
auto original_closure = std::bind(foo, myfoo(), 'a', _1);
auto final_closure = std::bind(
do_post<decltype(std::ref(original_closure)), int>, // signature deduced here
strand, std::ref(original_closure), _1); // std::ref used for inner std::bind
final_closure(99);
// others
}