0

Are there any limitations using boost's mapped_matrix with non-copyable objects like std::unique_ptr? I'm on VS2017 in C++14 mode.

#include <memory>
#include "boost/numeric/ublas/matrix_sparse.hpp"

class myClass
{
    public:
    myClass() {}
    void myMethod() {}
    /*...*/
};

void f()
{
    boost::numeric::ublas::mapped_matrix<std::unique_ptr<myClass>> SparseValues;
    //SparseValues(0, 0) = std::make_unique<myClass>(); // C2280, is it impossible to assign as the move assignment seems to be missing?
    auto p = std::make_unique<myClass>();
    //SparseValues(0, 0) = std::move(p);                // C2280

    auto a = SparseValues(0, 0);                        // Succeeds?? Expected it to fail, assuming it attempts to create a copy?
    auto &b = SparseValues(0, 0);                       // C4239: warning nonstandard extension used
    //auto c = SparseValues(0, 0).operator()();         // C2280, documentation for operator() says "Returns a reference of the j-th element in the i-th row", so there should be no copy?!
    auto &d = SparseValues(0, 0).operator()();          // Suceeds??
    //auto e = SparseValues(0, 0).ref();                // C2280, ref() is not ducumented but was worth a try
    //auto &f = SparseValues(0, 0).ref();               // C2440

    // OK, it seems not possible to get a reference, so then let's directly try to access an internal object:
    // Check for nullptr:
    //if (!SparseValues(0, 0)) { /*...*/ }              // Test for null: C2678, C2088
    //if (!SparseValues(0, 0)()) { /*...*/ }            // Test for null: C2678, C2088
    //if (!SparseValues(0, 0).ref()) { /*...*/ }        // Test for null: C2240
    //SparseValues(0, 0) = std::make_unique<myClass>(); // Reassign:      C2280
    //SparseValues(0, 0)->myMethod();                   // Call method:   C2819, C2039
    //SparseValues(0, 0)()->myMethod();                 // Call method:   C2819, C2039
    //SparseValues(0, 0).ref()->myMethod();             // Call method:   C2280
    //a = std::move(p);                                 // Assignment:    C2280
    //b = std::move(p);                                 // Assignment:    C2280
    //d = std::move(p);                                 // Assignment:    C2679
}

So this looks pretty useles to me! My questions are:

  • Is mapped_matrix indeed incapable to deal with uncopyable objects?
  • Is this by intention (due to architectural problems), or should I file a bugreport on this?
  • If however it can be used with non-copyables, how to properly use it?
  • The documentation of mapped_matrix is pretty, hm, poor. Anyone has another link giving more information? Like
    • What is the usage scenario of the functor and ref()? Is it correct that ref() guarantees that an object in the matrix exists (and if it'd be a default constructed object)?
    • What is the difference between the type "reference" returned by the functor and "true_refrence" returned by insert_element()? Sounds like the implementation bleeds through here?
    • What is the usage scenario of method assign_temporary()?

My workaround is of course to use std::shared_ptr, there it compiles without a problem...

Don Pedro
  • 335
  • 3
  • 7
  • Some more detailed error messages would be usefull. Just seeing the error code from the VS compiler is not very helpful. For example `SparseValue(0,0) = make_unique...` should tell you the type of the returned value of `SparseValue`. If it's a non-const reference to a `std::unique_ptr` the assignement would be possible, so it probably returns something else. – super Jan 29 '20 at 15:04
  • Well, most errors are C2280, this is "attempt to acces a deleted function". See here: https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2280?view=vs-2019 It always stems from the attempt to copy a unique_ptr (or in general a non-copyable object), a distinct hint that mapped_matric is lacking the move assignment operator. C2678 ist from the attempt to apply the negator (!) to a class: https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c2678?view=vs-2019 SparseValues(0, 0) does not return a reference to unique_ptr – Don Pedro Jan 30 '20 at 08:53
  • C2819 is "no operator -> defined on this class": https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c2819?view=vs-2019 Also a sign that the returned object/reference/whatever of SparseValues(0, 0) is not transparently simulating as if it was a unique_ptr. I think I have two problems: One is that I'm lacking sufficient knowledge about mapped_matrix (due to poor documentation in boost). And the other is that mapped_matrix does not support non-copyable objects and I'm wondering if this is just inattentiveness of the creator or if there is a technical reason. – Don Pedro Jan 30 '20 at 09:05
  • I think you're correct, the main problem is that the implementation of `mapped_matrix` does not have good support for move-only types. – super Jan 30 '20 at 10:56

0 Answers0