Это ошибка в API Mac OS X 10.6 C ++ std? - PullRequest
6 голосов
/ 09 апреля 2011

Следующий код не будет компилироваться в Mac OS X 10.6;он выдает ошибку в stl_algobase.h после списка сообщений «экземпляр из [...]».

#include <vector>

int main( void )
{
    std::vector<int*> *v = new std::vector<int*>( 1, NULL );

    return 0;
}  

Чтобы его скомпилировать, я должен поместить явное приведение вокруг NULL, то есть заменить его на (int*)(NULL).
Хотя это выглядит немного неловко, и я сомневаюсьэто должно быть действительно необходимо;это также делает мой исходный код довольно странным со структурами и более длинными именами типов, вложенными в пространства имен и т. д.

РЕДАКТИРОВАТЬ (сообщение об ошибке):

/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h: In static member function 'static _OutputIterator std::__fill_n<true>::fill_n(_OutputIterator, _Size, const _Tp&) [with _OutputIterator = int**, _Size = int, _Tp = int]':
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h:665:   instantiated from '_OutputIterator std::fill_n(_OutputIterator, _Size, const _Tp&) [with _OutputIterator = int**, _Size = int, _Tp = int]'
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h:184:   instantiated from 'void std::__uninitialized_fill_n_aux(_ForwardIterator, _Size, const _Tp&, std::__true_type) [with _ForwardIterator = int**, _Size = int, _Tp = int]'
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h:219:   instantiated from 'void std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = int**, _Size = int, _Tp = int]'  
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h:306:   instantiated from 'void std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>) [with _ForwardIterator = int**, _Size = int, _Tp = int, _Tp2 = int*]'  
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h:790:   instantiated from 'void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_Integer, _Integer, std::__true_type) [with _Integer = int, _Tp = int*, _Alloc = std::allocator<int*>]'  
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_vector.h:261:   instantiated from 'std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = int, _Tp = int*, _Alloc = std::allocator<int*>]'  
/Users/JayZ/projects/C++/test/main.cpp:6:   instantiated from here
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h:641: error: invalid conversion from 'const int' to 'int*'  

Если это могло бы помочь ...

Ответы [ 2 ]

7 голосов
/ 09 апреля 2011

Происходит следующее: компилятору приходится выбирать между одной из перегрузок конструктора vector, которая допускает более одного аргумента:

explicit vector(size_type n, const T& value = T(),
    const Allocator& = Allocator());

template <class InputIterator>
    vector(InputIterator first, InputIterator last,
        const Allocator& = Allocator());

Первая перегрузка (которую вы хотите сопоставить) требует преобразования аргументов. Второй не требует преобразования, так как 2 аргумента имеют одинаковый тип. Это перегрузка, которую выбирает компилятор. К сожалению, тип int не имеет всех операций, которые второй конструктор использует для этих аргументов.

Если аргументы будут разных типов, приведите NULL к int* или оставив первый аргумент без знака (1U), как правильно предлагают другие ответы, позволит избежать проблемы, заставив компилятор выбрать первый параметр конструктора. .

Обновление:

Когда я компилирую это с MinGW 4.5.2, я получаю ошибки компиляции (разные, но, по-моему, по той же причине). Однако, когда я строю с MSVC (2008 или 2010), я не получаю ошибок. Когда я смотрю на код, который генерирует MSVC, он фактически соответствует второй перегрузке (с 2 итераторами), а не перегрузке «размер и значение по умолчанию».

«Ага», я думаю, «это может произойти сбой во время выполнения где-то, потому что итераторы со значениями 1 и 0 не имеют никакого смысла».

Однако, когда типы итераторов этого конструктора оказываются равными int, реализация MSVC выполняет конструкцию 'count / начальное значение' vector.

Стандарт говорит, что должен делать этот конструктор, когда аргументы InputIterator конструктора удовлетворяют требованиям InputIterator. Поскольку int не соответствует требованиям InputIterator, реализация имеет некоторое свободное право делать что-то еще. Стандарт гласит: «Реализация может объявлять дополнительные не виртуальные сигнатуры функций-членов в классе» (17.4.4.4), и это, я думаю, будет охватывать поведение MSVC. Поведение, которое вы видите и которое я вижу в GCC 4.5.2, производящем диагностику ошибок, также разрешено стандартом.

Я уверен, что поведение MSVC - это то, что большинство пользователей хотят и хотят (пока они не перейдут к коду в какой-то другой компилятор, может быть). И это, конечно, умно.

1 голос
/ 09 апреля 2011

Код, который вы разместили, компилируется для меня на OS X 10.6.7.Я добавил в некоторые утверждения только для того, чтобы доказать, что он делает то, что должно быть ...

bash-3.2$ cat test.cpp 
#include <vector>
#include <cassert>

int main()
{
    std::vector<int*> *v = new std::vector<int*>( 1, NULL );
    assert(v != NULL);
    assert(v->size() == 1);
    assert(v->at(0) == NULL);
    assert(false);
    return 0;
}  

bash-3.2$ 
bash-3.2$ g++ -Wall -Wextra -Weffc++ test.cpp 
bash-3.2$ ./a.out 
Assertion failed: (false), function main, file test.cpp, line 10.
Abort trap
bash-3.2$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

assert(false) является преднамеренным: -)

С помощью1007 * Mackie Messer's answer Я могу воспроизвести вашу ошибку с помощью -m32.Эта строка исправляет это (и более аккуратно, чем приведение IMHO):

std::vector<int*> *v = new std::vector<int*>(1U, NULL);

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...