Пытаюсь использовать std::bind
с методом класса:
#include <iostream>
#include <functional>
class Test{
public:
void print(int a){
std::cout << a << std::endl;
}
};
int main() {
Test test;
std::bind(test, test.print, 5);
return 0;
}
Компилятор выдает следующую ошибку:
Reference to non-static member function must be called.
Как исправить?
Прежде, чем писать на все знакомые форумы первым делом лучше почитать документацию - там много полезного написано. Например сигнатура std::bind
:
template< class F, class... Args >
/*unspecified*/ bind( F&& f, Args&&... args );
Как видим, первым аргументом должен идти функтор, а у вас, почему-то объект test
.
Исправим:
std::bind(test.print, 5);
Однако получаем ошибку при попытке скомпилировать, на этот раз что-то вроде invalid non-static member function
- это потому что мы не можем вот так обращаться к методам объектам, вместо этого указатель на метод записывается так:
std::bind(&Test::print, 5);
Однако, как мы видим, мы имеем указатель на метод, но нигде не указываем сам объект - нам компилятор на этот раз сообщит о невалидном количестве параметров в функции. Все потому, что в методах (не статических) всегда есть минимем один аргумент - это this. И хоть он не указывается при определении метода, это тем не менее самый настоящий аргумент.
Как результат в итге получаем:
std::bind(&Test::bind, &test, 5);
UDP Тут в комментах также подсказали, что можно к методу биндить не только указатель, но и ссылку - это абсолютно верно, но есть одно большое НО, о чем автор коммента забыл упомянуть. Давайте разберемся что за но.
std::bind(&Test::print, test, 5);
С первого взгляда все ок, все работает как ожидается, но давайте немного усложним класс Test
. Предположим это объект который содержит сокет и во время вызова print
пишет что-то в сокет. Сокет такая вещь, которую лучше не копировать, поэтому пометим наш класс как nocopyable
class Test {
...
Test() = default;
Test(const Test &) = delete;
}
И что же мы увидим при попытке компиляции? Ошибку. Компилятор нам сообщит, что не может скопировать объект test
чтобы использовать его в std::bind
. Как видим, подобныя ситуация может быть весьма и весьма чревата в реальной ситуации. К счастью она весьма просто исправляется: нужно указать, что мы передаем test
именно по ссылке
std::bind(&Test::print, std::ref(test), 5);
Данные момент нужно знать обязательно, так как не зная об этом вы можете провести много времени в дебаге пытаяся разобраться в том, почему изменяя объект вы никак не влияете на результат
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть вектор std::vector<uint8_t> From; Он содержит 10^9 элементов
Прошу, помогите найти код в ошибке и решить проблему, а то моя тупая головушка не может понять конкретного местаПрошу, не судите строго, я новичок...
У меня не много опыта с С++, но вот, что мне нужно сделатьУ меня есть метод который должен скастить unsigned char const * к void*