std::функция внутри класса шаблона, выдающая ошибку создания объекта

#c #c 11 #std-function

Вопрос:

Получение ошибки ниже для кода, приведенного ниже. Попытка создать 3 функции std::внутри класса шаблона, а затем инициализировать их различными функциями из разных классов.

Почему происходит эта ошибка? Что не так с нижеприведенным кодом?

введите описание изображения здесь

 template <typename T>
class CFuntion {
public:
    std::function<void()> callback_1;
    std::function<void()> callback_2;
    std::function<void()> callback_3;

    template <typename A, typename B, typename C>
    CFuntion(A cb1, B cb2, C cb3)
        : callback_1(cb1), callback_2(cb2), callback_3(cb3)
    { }
};

class Impl1 {
public:
    void do_something1() {
        cout << "Inside Impl1 do_something1" << endl;
    }

    void do_something2() {
        cout << "Inside Impl1 do_something2" << endl;
    }
};

class Impl2 {
public:
    void do_something1() {
        cout << "Inside Impl2 do_something1" << endl;
    }

    void do_something2() {
        cout << "Inside Impl2 do_something2" << endl;
    }
};

class Impl3 {
public:
    void do_something1() {
        cout << "Inside Impl3 do_something1" << endl;
    }

    void do_something2() {
        cout << "Inside Impl3 do_something2" << endl;
    }
};

int main()
{
    unique_ptr<CFuntion<void>> ptr1 = make_unique<CFuntion<void>>(std::bind(amp;Impl1::do_something1, amp;Impl2::do_something1, 
                                        amp;Impl3::do_something2));
    ptr1->callback_1();
    ptr1->callback_2();
    ptr1->callback_3();

    system("pause");
    return 0;
}
 

Комментарии:

1. CFunction<void> имеет два конструктора — указанный вами конструктор, который принимает три аргумента, и конструктор копирования, который принимает const CFunction<void>amp; . Вы пытаетесь передать один аргумент, который является выражением привязки, std::bind(x, y, z) . Ни один из конструкторов не может принять этот аргумент.

2. Кроме того, ваше выражение привязки не имеет никакого смысла: вы просите его вызвать Impl1::do_something1 с двумя аргументами amp;Impl2::do_something1 и amp;Impl3::do_something2 . Вы, вероятно, имели в виду три отдельных bind звонка. Но простой std::bind(amp;Impl1::do_something1) тоже не будет работать — do_something1 это нестатическая функция-член, и для ее вызова требуется экземпляр Impl1 . В общем, непонятно, чего вы пытаетесь достичь.

3. @IgorTandetnik — я также пытался с этим кодом, но это тоже не удается, unique_ptr<CFuntion<void><void>> ptr1 = make_unique<void>><CFuntion<void><void>>(std::привязка(amp;Impl1::do_something1), std::привязка(amp;Impl2::do_something1), std::привязка(amp;Impl3::do_something2));

4. Мой второй комментарий касается этого.

Ответ №1:

Посмотрите на эту часть:

 unique_ptr<CFuntion<void>> ptr1 = make_unique<CFuntion<void>(std::bind(amp;Impl1::do_something1, amp;Impl2::do_something1, amp;Impl3::do_something2));
//                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

Здесь вы передаете только один объект своему CFunction<void> конструктору. То, что вам нужно, может быть, это:

 // You need to pass temporary objects to 'std::bind()' to bind non-static member functions
Impl1 obj1;
Impl2 obj2;
Impl3 obj3;
std::unique_ptr<CFuntion<void>> ptr1 = std::make_unique<CFuntion<void>>(std::bind(amp;Impl1::do_something1, obj1), std::bind(amp;Impl2::do_something1, obj2), std::bind(amp;Impl3::do_something2, obj3));
 

Или, посмотрев на ваши Impl1 Impl2 Impl3 классы и , кажется, вы могли бы просто создать их методы-члены static (поскольку ни один из этих трех классов, похоже, не нуждается в каком-либо различии между их объектами или имеет какие-либо переменные экземпляра для доступа/изменения).:

 class Impl1 {
public:
    static void do_something1() {
        cout << "Inside Impl1 do_something1" << endl;
    }

    static void do_something2() {
        cout << "Inside Impl1 do_something2" << endl;
    }
};

class Impl2 {
public:
    static void do_something1() {
        cout << "Inside Impl2 do_something1" << endl;
    }

    static void do_something2() {
        cout << "Inside Impl2 do_something2" << endl;
    }
};

class Impl3 {
public:
    static void do_something1() {
        cout << "Inside Impl3 do_something1" << endl;
    }

    static void do_something2() {
        cout << "Inside Impl3 do_something2" << endl;
    }
};
 

Таким образом, вам просто нужно сделать это, что, по-видимому, и есть то, что вы хотите сделать:

 std::unique_ptr<CFuntion<void>> ptr1 = std::make_unique<CFuntion<void>>(std::bind(amp;Impl1::do_something1), std::bind(amp;Impl2::do_something1), std::bind(amp;Impl3::do_something2));
 

Комментарии:

1. Спасибо за ответ. Однако один вопрос: если мне нужно передать аргументы функциям do_something, как это можно сделать?

2. Вы можете поместить значения аргументов в std::bind std::bind(amp;Impl1::do_something1, 12, "abc", 'a') , и т.д. Кроме того, страница std::bind() cppreference может быть полезна для вас .