Is this a bug in Mac OS X 10.6 C ++ std API?

The following code will not compile on Mac OS X 10.6; it throws an error in stl_algobase.h, following the list of "messages created from [...]".

#include <vector> int main( void ) { std::vector<int*> *v = new std::vector<int*>( 1, NULL ); return 0; } 

To compile it, I have to put an explicit expression around NULL , i.e. replace it with (int*)(NULL) .
However, this looks awkward, and I doubt it is really necessary; it also makes my source code rather strange with structures and longer type names nested in namespaces, etc.

EDIT (error message):

 /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*' 

If this can help ...

+6
source share
2 answers

What happens is that the compiler must select one of the overloads of the vector constructor, which allows more than one argument:

 explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator()); template <class InputIterator> vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); 

The first overload (which you want to match) requires argument conversion. The second does not require conversion, since 2 arguments are of the same type. So the overload that the compiler chooses. Unfortunately, the int type does not have all the operations that the second constructor uses for these arguments.

Forcing arguments to different types by dropping NULL to int* or by creating the first argument unsigned ( 1U ), since the correct hints can avoid the problem by forcing the compiler to choose the first constructor option.

Update:

When I compile this with MinGW 4.5.2, I get compilation errors (different, but for the same reason, I think). However, when I create MSVC (2008 or 2010), I get no errors. When I look at the code that MSVC generates, it actually maps the second overload (with 2 iterators), not the "size and default value" overload.

β€œYeah,” I think, β€œit will happen somewhere at runtime because iterators with values 1 and 0 make no sense.”

However, when the "iterator" types of this constructor turn out to be int , the MSVC implementation executes the "count / initial value" vector construct.

The standard states what this constructor should do if the arguments to the InputIterator constructor meet the requirements of the InputIterator. Since int does not meet the requirements of InputIterator, the implementation has some loose control to do something else. The standard says that "an implementation may declare additional non-virtual signatures of member functions within a class" (17.4.4.4), and this, in my opinion, will cover the behavior of MSVC. The behavior that you see and that I see with GCC 4.5.2, which creates error diagnostics, is also allowed by the standard.

I am sure that the behavior of MSVC is what most users want and want (until they move to another compiler for the code). And it is certainly smart.

+6
source

The code you posted compiles for me on OS X 10.6.7. I added in some statements just to prove that he is doing what it looks like it should be ...

 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) intentionally :-)

Thanks Answer Mackie Messer I can reproduce your error using -m32 . This line captures this (and more accurately than casting IMHO):

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

Hope this helps.

+1
source

Source: https://habr.com/ru/post/885569/


All Articles