2011-05-15 4 views
2

Почему мой VS2010 не может скомпилировать этот код:Использование станд :: tr1 :: связывают с станд :: вектор :: push_back

#include <functional> 
#include <vector> 
int main() 
{ 
    std::vector<int> vec; 
    std::bind(&std::vector<int>::push_back, std::ref(vec), 1)(); 
    return 0; 
} 
+1

Пожалуйста, вставьте в ошибку вы получаете. Даже если мы готовы помочь, мы не экстрасенсы. – ereOn

+0

Я не вижу ошибки в этом. Я запускаю этот код, и он работает хорошо. Обязательно включите tr1/functional. –

+0

Он не компилируется в VS2010, нет заголовка , только . Что я делаю не так? – magenta

ответ

3

Попробуйте это:

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)(); 

С C++ 03 отмечают, что push_back не может быть локальный тип; с C++ 11 он может, но было бы более идиоматично (и полностью эквивалентно) использовать лямбда.

По всей видимости, ваша реализация обеспечивает перегрузку для std::vector<T>::push_back, и поэтому ее адрес должен быть устранен. Если это так, ваш компилятор должен предоставить вам соответствующее сообщение об ошибке. В статьях все случаях вы должны объяснить, что вы подразумеваете под словом «это невозможно».


Дело не в том, чтобы использовать такие, Helper функции. - magenta

Тогда почему вы не задали вопрос? Я не могу читать ваши мысли.

Вы также можете попробовать это:

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)(); 

который я считаю, не гарантируется успех.

+2

Дело не в использовании таких вспомогательных функций. – magenta

+2

@magenta Пожалуйста, внесите изменения в свой вопрос, тогда –

0

Он должен Propably Лок, как это:

std::vector<int> vec; 
std::tr1::bind(&std::vector<int>::push_back, std::tr1::ref(vec), _1)(1); 
+0

Не имеет значения. – magenta

5

Вы должны быть более конкретными, почему это не работает для вас.

#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 

Update: Люк Дантон правильно, вопрос здесь перегруженный push_back. См. Вопрос Are there boost::bind issues with VS2010 ?. Также обратите внимание, что проблема не ограничивается push_back, см. Visual Studio 2010 and boost::bind.

+0

Он просто не компилируется. И проблема, похоже, в #include . Я использую VS2010, и нет такого заголовка. – magenta

+0

@magenta: VS2010 просто не имеет заголовков tr1, они встроены в не-tr1. Кроме того, VS2010 импортирует все важные имена tr1 в обычном пространстве имен std, поэтому просто включите '' и используйте' std :: bind', без 'tr1'. – Xeo

4

Суть в том, что то, что вы пытаетесь сделать, невозможно в portable C++. std::vector<>::push_back гарантированно будет перегружен в компиляторах C++ 11, поскольку, как минимум, должна быть перегрузка для lvalues ​​и перегрузка для rvalues.

Обычно, принимая адрес перегруженной функции члена, §13.4/1 в C++ 11 FDIS говорит нам, что мы можем контролировать, какие перегружать мы берем адрес таким образом:

Использование перегруженного имени функции без аргументов разрешено в определенных контекстах функции, указателю на функцию или указателю на функцию-член для определенной функции из набора перегрузки. Имя шаблона функции считается названным набором перегруженных функций в таких контекстах. Выбранная функция - это тип, идентичный типу функции целевого типа, требуемого в контексте. [Примечание: То есть, класс, членом которого является член, игнорируется при сопоставлении типа указателя-члена.-end примечание] Мишень может быть

  • объект или ссылка инициализируется,
  • левая сторона присваивания,
  • параметр функции,
  • параметр пользователя -определенной оператор,
  • возвращаемого значения функции, функций оператора, или преобразований,
  • явного преобразования типов, или
  • не-тип шаблона-параметра.

Перегруженному имени функции может предшествовать оператор &. Перегруженное имя функции не должно использоваться без аргументов в других контекстах, кроме перечисленных. [Примечание: Любой избыточный набор круглых скобок, окружающих перегруженное имя функции, игнорируется. -end примечание]

Проблема происходит от §17.6.5.5/2:

Реализация может объявить дополнительные невиртуальные сигнатуры функций члена в классе, добавив аргументы по умолчанию значения для сигнатуры функции-члена; , следовательно, адрес функции-члена класса в стандартной библиотеке C++ имеет неопределенный тип.

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

предложил Люк Дантона обходной путь (в частности, с использованием лямбда) также то, что я бы рекомендовал:

std::vector<int> vec; 
[&](){ vec.push_back(1); }(); 
+0

Да, лямбда, вероятно, лучший выбор здесь, если мы используем C++ 0x. Но на самом деле мне было просто любопытно, почему VS2010 не смог скомпилировать мой код. – magenta

Смежные вопросы