Почему мой VS2010 не может скомпилировать этот код:
#include <functional>
#include <vector>
int main()
{
std::vector<int> vec;
std::bind(&std::vector<int>::push_back, std::ref(vec), 1)();
return 0;
}
Почему мой VS2010 не может скомпилировать этот код:
#include <functional>
#include <vector>
int main()
{
std::vector<int> vec;
std::bind(&std::vector<int>::push_back, std::ref(vec), 1)();
return 0;
}
Попробуй это:
struct push_back {
void
operator()(std::vector<int>& vector, int i) const
{
vector.push_back(i);
}
};
// somewhere else:
std::vector<int> vec;
std::tr1::bind(push_back(), std::tr1::ref(vec), 1)();
С С++ 03 обратите внимание, что push_back
не может быть локальным типом; с С++ 11 это возможно, но было бы более идиоматично (и полностью эквивалентно) использовать лямбда.
По всей вероятности, ваша реализация предоставляет перегрузки для std::vector<T>::push_back
, поэтому его адрес должен быть устранен. Если это то, что произошло, ваш компилятор должен был предоставить вам соответствующее сообщение об ошибке. В всех случаях вы должны объяснить, что вы подразумеваете под "это невозможно".
Дело в том, чтобы не использовать такие вспомогательные функции. - пурпурный
Тогда почему вы не указали это в вопросе? Я не могу читать твои мысли.
Вы также можете попробовать это:
std::vector<int> vec;
void (std::vector<int>::*push_back)(int const&) = &std::vector<int>::push_back;
std::tr1::bind(push_back(), std::tr1::ref(vec), 1)();
Что, я считаю, не гарантирует успеха.
Вы должны быть более конкретными, почему это не работает для вас.
#include <iostream>
#include <tr1/functional>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int> vec;
std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), 1)();
std::cout << "vec.size = " << vec.size() << std::endl;
std::cout << "vec[0] = " << vec[0] << std::endl;
return 0;
}
$ gcc -o test -lstdc++ test.cpp && ./test
vec.size = 1
vec[0] = 1
Обновление: Люк Дантон прав, проблема здесь в перегруженном push_back
. См. вопрос Есть ли проблемы boost::bind с VS2010?. Также обратите внимание, что проблема не ограничивается push_back
, см. Visual Studio 2010 и boost::bind.
<functional>
и используйте std::bind
без tr1
.
- person Xeo; 15.05.2011
Суть в том, что то, что вы пытаетесь сделать, невозможно в portable C++. std::vector<>::push_back
гарантированно будет перегружен в компиляторах C++11, поскольку как минимум должна быть перегрузка для lvalue и перегрузка для rvalue.
Обычно при получении адреса перегруженной функции-члена §13.4/1 в FDIS C++11 говорит нам, что мы можем контролировать, адрес какой перегрузки мы берем следующим образом:
Использование имени перегруженной функции без аргументов разрешается в определенных контекстах для функции, указателя на функцию или указателя на функцию-член для конкретной функции из набора перегрузки. В таких контекстах считается, что имя шаблона функции именует набор перегруженных функций. Выбрана функция, тип которой идентичен типу функции целевого типа, необходимого в контексте. [ Примечание: То есть класс, к которому относится функция. член игнорируется при сопоставлении типа указателя на функцию-член. —конец примечания ] Цель может быть
- инициализируемый объект или ссылка,
- левая часть задания,
- параметр функции,
- параметр пользовательского оператора,
- возвращаемое значение функции, операторной функции или преобразования,
- явное преобразование типа или
- параметр-шаблона, не являющийся типом.
Перед именем перегруженной функции может стоять оператор
&
. Имя перегруженной функции не должно использоваться без аргументов в контекстах, отличных от перечисленных. [ Примечание. Любой лишний набор скобок, окружающих имя перегруженной функции, игнорируется. —конец примечания ]
Проблема возникает из §17.6.5.5/2:
Реализация может объявлять дополнительные невиртуальные сигнатуры функций-членов внутри класса, добавляя аргументы со значениями по умолчанию к сигнатуре функции-члена; поэтому адрес функции-члена класса в стандартной библиотеке C++ имеет неопределенный тип.
Следовательно, невозможно когда-либо взять адрес функции-члена класса стандартной библиотеки, поскольку тип такого выражения по определению неизвестен, кроме как на основе реализации за реализацией.
Предложенный Люком Дантоном обходной путь (в частности, с использованием лямбды) также является тем, что я бы порекомендовал:
std::vector<int> vec;
[&](){ vec.push_back(1); }();
Вероятно, это должно выглядеть так:
std::vector<int> vec;
std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), _1)(1);
std::bind
, просто включите<functional>
. - person Paul Michalik   schedule 15.05.2011