3

I try to create a compressed_matrix using a coordinate_matrix as a builder:

#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>

using namespace boost::numeric::ublas;

int main(int argc, char** argv) {
  coordinate_matrix<int> m1(100, 100, 100);

  for (int i = 0; i < 100; i++)
    m1.insert_element(i,i,i);

  compressed_matrix<int> m2(m1, 100);
}

This seems to work fine using boost 1.54 and clang, but when I compile it using std=c++11, an error is thrown:

 choeger@daishi /tmp % clang++ test.cpp --std=c++11
In file included from test.cpp:1:
In file included from /usr/include/boost/numeric/ublas/io.hpp:18:
In file included from /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/sstream:38:
In file included from /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/istream:38:
In file included from /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/ios:40:
In file included from /usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/bits/char_traits.h:39:
/usr/bin/../lib/gcc/x86_64-redhat-linux/4.8.2/../../../../include/c++/4.8.2/bits/stl_algobase.h:147:7: error: no matching function for call to 'swap'
      swap(*__a, *__b);

Are there known incompatibilities of boost 1.54 with C++11? Or did I make some C++11 error? The 1.55 changelog does not mention ublas nor matrices, so I guess it is still present.

This happens both with gcc 4.8.2 and clang 3.4

choeger
  • 3,562
  • 20
  • 33
  • 3
    [This](http://boost.2283326.n4.nabble.com/index-pair-array-and-index-triple-array-on-gcc4-8-c-11-td4661142.html) seems to explain the problem. [Copying one of the workarounds for older compilers in "boost/numeric/ublas/detail/config.hpp" seems to make it compile](http://coliru.stacked-crooked.com/a/381cf2a0735924d8) (although I don't know if it behaves as it should at runtime because I have never used uBLAS and have no idea what you are trying to do). Hope this helps (but don't be surprised if it doesn't). – llonesmiz Jun 15 '14 at 12:02
  • Could you make this an answer? – choeger Jun 15 '14 at 13:09
  • 1
    I don't feel confident giving an answer about something I know so little about. Feel free to add your own answer if you understand the problem/solution (I'll upvote it). – llonesmiz Jun 15 '14 at 15:12

2 Answers2

3

This is definitely a bug in Boost. The problem is that when BOOST_UBLAS_STRICT_MATRIX_SPARSE is defined, coordinate_matrix and its iterator types use a proxy class as their reference type:

#ifndef BOOST_UBLAS_STRICT_MATRIX_SPARSE
        typedef T &reference;
#else
        typedef sparse_matrix_element<self_type> reference;
#endif

which violates the C++ standard's requirement that the reference type for forward iterators is a true reference. C++11 [forward.iterators]/1 states: "A class or pointer type X satisfies the requirements of a forward iterator if ... if X is a mutable iterator, reference is a reference to T; if X is a const iterator, reference is a reference to const T, ...".

The coordinate_matrix iterators claim to be bidirectional iterators despite this fact, resulting in undefined behavior.

Casey
  • 41,449
  • 7
  • 95
  • 125
1

To answer my own question:

Thanks to @cv_and_he's comment, I figured the following part of the C++ reference is relevant here (because coordinate_matrix calls std::sort):

Random-access iterators to the initial and final positions of the sequence to be sorted. The range used is [first,last), which contains all the elements between first and last, including the element pointed by first but not the element pointed by last. RandomAccessIterator shall point to a type for which swap is properly defined and which is both move-constructible and move-assignable.

Apparently, the swap method is not defined properly (whatever that means).

Bug is reported here.

choeger
  • 3,562
  • 20
  • 33