std :: bind функции-члена с идеальной пересылкой - PullRequest
0 голосов
/ 07 ноября 2019

У меня есть требование, где мне нужно связать функцию-член и передать аргументы с идеальной пересылкой. Это часть большей кодовой базы. Таким образом, код может не показаться актуальным. Но мне нужно исправить это, чтобы двигаться вперед.

Мне известно о решении лямбда-функций, и оно прекрасно работает, но я не хочу его использовать и понимаю , почему std :: bindошибочно полагает, что аргумент, переданный для вызова связанной функции-члена, является аргументом этой функции

Точная ошибка компилятора:

: 52: 5: error:нет соответствующей функции для вызова объекта типа 'std :: _ Bind :: * (std :: _ Placeholder <1>, B)) (B)>' binder (& a);

Но,ожидаемая интерпретация должна быть следующей: 'std :: _ Bind :: * (B)) (B)>'

#include <functional>

struct B{
    B(const B&) = delete;
    B(){}
    B(B &&b){}
};

template<typename Ret, typename... Args>
struct A{
    Ret send(Args... argx){
        return Ret();
    }
};

//<---------   Code above this line cannot be changed ----------->

template<class Ret, class ...Args>
void bind_and_forward(Args... args)
{
    using ConnectionType = A<Ret, Args...>;
    auto binder = std::bind(&ConnectionType::send,std::placeholders::_1,std::forward<Args>(args)...);

    ConnectionType a; 
    binder(&a);
    //^---compiler error here
}

int main()
{
    B b;
    bind_and_forward<int>(std::move(b));
}

1 Ответ

1 голос
/ 07 ноября 2019

Вы действительно не можете использовать лямбда-решение? Жаль.

В любом случае ... в вашем коде есть некоторые проблемы.

Если вы хотите использовать совершенную пересылку в bind_and_forward(), вам нужно использовать ссылки для пересылки, поэтому вам нужно добавить&& после Args объявления аргументов функции

template <class Ret, class ...Args>
void bind_and_forward (Args && ... args)
// .........................^^

, и я также предлагаю позволить компилятору выводить типы Args..., не объясняя их при вызове bind_and_forward()

bind_and_forward<int>(std::move(b));
// ..............^^^ only the return type

Но реальная проблема (проблема, которая вызывает ошибку компиляции) состоит в том, что вы удалили B конструктор копирования

struct B{
    B(const B&) = delete; // <-- copy constructor deleted
    B(){}
    B(B &&b){}
};

, но вы получили аргументы (также B) при копированиив A::send()

template<typename Ret, typename... Args>
struct A{
    Ret send(Args... argx){  // <-- argx are copies
        return Ret();
    }
};

Вы должны выбрать: вы можете добавить конструктор копирования в B

struct B{
    B(const B&) = default; // <-- now you have copy constructor
    B(){}
    B(B &&b){}
};

или вы можете получить argx в качестве константных ссылок (избегая копирования)

template<typename Ret, typename... Args>
struct A{
    Ret send(Args const & ... argx){ // <-- now by const reference
        return Ret();
    }
};
...