Search code examples
c++c++11stlstl-algorithm

C++: STL sort STL vector of STL array


The following C++ Code and Makefile produce a compilation error incomprehensible (to me). Can somebody explain

  1. What precisely is the problem?

  2. What needs to be done to fix this code? Can you give an example?

I had this code compile successfully on a GCC in Cygwin, so I am not even sure which compiler I can trust. I am attaching the cpp file (test.cpp), my makefile (using clang because the GCC error message is even worse) and the actual error message on running make.

test.cpp:

#include <array>
#include <vector>
#include <map>
#include <algorithm>

class Foo
{

    public:

        Foo( 
            const std::vector<std::array<int,3>> inputdata
        );

    private:

        std::vector< std::array<int,2> > membervariable;

};

Foo::Foo( 
    const std::vector<std::array<int,3>> inputdata
)
:
    membervariable( 0 )
{

    /* 1. create all edges, allocate memory */

    membervariable.resize( inputdata.size() * 3 );

    for( int t  = 0; t  < inputdata.size(); t++  )
    for( int ei = 0; ei <                        3; ei++ )
    {
      membervariable[ 0 * inputdata.size() + t ] = { inputdata[t][0], inputdata[t][1] };
      membervariable[ 1 * inputdata.size() + t ] = { inputdata[t][0], inputdata[t][2] };
      membervariable[ 2 * inputdata.size() + t ] = { inputdata[t][1], inputdata[t][2] };
    }

    std::sort( membervariable.begin(), membervariable.end() );

    auto it = std::unique( membervariable.begin(), membervariable.end() );

    membervariable.resize( it - membervariable.begin() );


}

makefile:

CC = clang++ -O0 -g -std=c++11 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -pedantic -Wall -Wextra -Wno-unused-variable -Wno-sign-compare -Wno-missing-braces -Wmissing-field-initializers -Werror=implicit
# CC =     g++ -O0 -g -std=c++11 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -pedantic -Wall -Wextra -Wno-unused-variable -Wno-sign-compare -Wno-missing-braces -Wmissing-field-initializers -Werror=implicit

test.o: test.cpp
        $(CC) test.cpp -c -o test.o 

Output on envoking make and clang version:

$ make
clang++ -O0 -g -std=c++11 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -pedantic -Wall -Wextra -Wno-unused-variable -Wno-sign-compare -Wno-missing-braces -Wmissing-field-initializers -Werror=implicit test.cpp -c -o test.o
In file included from test.cpp:3:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/map:61:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_map.h:63:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/tuple:39:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/array:338:
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/debug/array:86:52: error: too many arguments to function call, expected
      single argument '__other', have 2 arguments
      noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
                        ~~~~                       ^~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/debug/array:264:23: note: in instantiation of exception specification for
      'swap' requested here
    noexcept(noexcept(__one.swap(__two)))
                      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algobase.h:148:7: note: in instantiation of exception
      specification for 'swap<int, 2>' requested here
      swap(*__a, *__b);
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algo.h:84:11: note: in instantiation of function template
      specialization 'std::iter_swap<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *,
      std::__cxx1998::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *, std::__cxx1998::vector<std::__debug::array<int, 2>,
      std::allocator<std::__debug::array<int, 2> > > >, std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int,
      2> > > > >' requested here
            std::iter_swap(__result, __b);
                ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algo.h:1916:12: note: in instantiation of function template
      specialization 'std::__move_median_to_first<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *,
      std::__cxx1998::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >, __gnu_cxx::__ops::_Iter_less_iter>'
      requested here
      std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algo.h:1948:11: note: in instantiation of function template
      specialization 'std::__unguarded_partition_pivot<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *,
      std::__cxx1998::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >, __gnu_cxx::__ops::_Iter_less_iter>'
      requested here
            std::__unguarded_partition_pivot(__first, __last, __comp);
                ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algo.h:1963:9: note: in instantiation of function template
      specialization 'std::__introsort_loop<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *,
      std::__cxx1998::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >, long,
      __gnu_cxx::__ops::_Iter_less_iter>' requested here
          std::__introsort_loop(__first, __last,
              ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_algo.h:4698:12: note: in instantiation of function template
      specialization 'std::__sort<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *,
      std::__cxx1998::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >, __gnu_cxx::__ops::_Iter_less_iter>'
      requested here
      std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
          ^
test.cpp:40:10: note: in instantiation of function template specialization
      'std::sort<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::__debug::array<int, 2> *,
      std::__cxx1998::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > >,
      std::__debug::vector<std::__debug::array<int, 2>, std::allocator<std::__debug::array<int, 2> > > > >' requested here
    std::sort( membervariable.begin(), membervariable.end() );
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/debug/array:84:7: note: 'swap' declared here
      void
      ^
1 error generated.
makefile:6: recipe for target 'test.o' failed
make: *** [test.o] Error 1
$ clang++ --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$

Solution

  • The error messages shown in the question concerns a bug in the standard (LWG issue 2456) that GCC's standard library had implemented to the letter. GCC's compiler didn't diagnose the problem with the resulting code (otherwise the bug would have been discovered earlier), but the version of clang you used does. IIRC clang later added a special hack to allow this particular usage to compile, so the "fix" is to use a newer version of GCC or a newer version of Clang or both.