New user self-registration is currently disabled. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Bug 920 - VC++ 2015 compiler error: deleted copy assignment operator for Block (and base classes)
VC++ 2015 compiler error: deleted copy assignment operator for Block (and bas...
Status: RESOLVED FIXED
Product: Eigen
Classification: Unclassified
Component: Core - general
3.3 (current stable)
All Windows
: Normal Compilation Problem
Assigned To: Nobody
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2014-12-16 15:13 UTC by Michael Hofmann
Modified: 2014-12-18 23:05 UTC (History)
3 users (show)



Attachments

Description Michael Hofmann 2014-12-16 15:13:41 UTC
I am failing to compile the following simple program using VC++ 2015 Preview and Eigen changeset ccf109e3b393 (tip, as of writing):

---
#include <Eigen/Core>

int main()
{
    Eigen::Matrix3f m = Eigen::Matrix3f::Zero();
    Eigen::Matrix3f n = Eigen::Matrix3f::Zero();
    m.block<2, 2>(0, 0) = n.block<2, 2>(0, 0);
}
---

The compiler complains that the copy assignment operator of Block<> is deleted:

1>test.cpp(66): error C2280: 'Eigen::Block<Derived,2,2,false> &Eigen::Block<Derived,2,2,false>::operator =(const Eigen::Block<Derived,2,2,false> &)': attempting to reference a deleted function
1>          with
1>          [
1>              Derived=Eigen::Matrix<float,3,3,0,3,3>
1>          ]
1>  eigen\eigen\src\core\block.h(148): note: compiler has generated 'Eigen::Block<Derived,2,2,false>::operator =' here
1>          with
1>          [
1>              Derived=Eigen::Matrix<float,3,3,0,3,3>
1>          ]

which might or might not be a valid complaint, since the class contains non-static const variables.
See also http://en.cppreference.com/w/cpp/language/as_operator#Deleted_implicitly-declared_copy_assignment_operator.

I have tried adding an explicit definition for the copy assignment operator by calling the respective operator of its base class and returning *this, but this operation becomes viral. The compiler appears to require explicit copy assignment operator definitions for all base classes. (And I don't really want to patch this myself for our code base, because I'd probably get it wrong...)

What is the best solution here - just adding explicit definitions for all copy assignment operators up the inheritance hierarchy? Or something else?
Comment 1 Christoph Hertzberg 2014-12-16 15:56:14 UTC
(In reply to Michael Hofmann from comment #0)
> I have tried adding an explicit definition for the copy assignment operator
> by calling the respective operator of its base class and returning *this,

That should be exactly what line 110 does:
https://bitbucket.org/eigen/eigen/src/ccf109e3b393/Eigen/src/Core/Block.h?at=default#cl-110

But that definition is not enabled if EIGEN_COMP_MSVC_STRICT is true.
Could you change line 595 in src/Core/util/Macros.h to:

#if EIGEN_COMP_MSVC_STRICT && EIGEN_COMP_MSVC < 1900

and report what happens?
Comment 2 Michael Hofmann 2014-12-16 17:42:15 UTC
My version of src/Core/util/Macros.h (from tip of default) doesn't even have that many lines (it has 468), but I have changed line 340 like this:

$ hg diff
diff -r 3cc5093598e5 src/Eigen/Eigen/src/Core/util/Macros.h
--- a/src/Eigen/Eigen/src/Core/util/Macros.h    Tue Dec 16 15:49:46 2014 +0100
+++ b/src/Eigen/Eigen/src/Core/util/Macros.h    Tue Dec 16 17:15:00 2014 +0100
@@ -337,7 +337,7 @@
 // just an empty macro !
 #define EIGEN_EMPTY

-#if defined(_MSC_VER) && (!defined(__INTEL_COMPILER))
+#if defined(_MSC_VER) && (_MSC_VER < 1900) && (!defined(__INTEL_COMPILER))
 #define EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Derived) \
   using Base::operator =;
 #elif defined(__clang__) // workaround clang bug (see http://forum.kde.org/viewtopic.php?f=74&t=102653)

This fixes the above compiler error but triggers another error further up the chain, in MapBase<>:

1>eigen\src/Core/MapBase.h(246): error C3083: '{ctor}': the symbol to the left of a '::' must be a type

and the code in question is:

    EIGEN_DEVICE_FUNC
    Derived& operator=(const MapBase& other)
    {
      Base::Base::operator=(other);    // line 246
      return derived();
    }

If I now change line 246 to 'Base::operator=(other);', then the compiler also complains about a deleted copy assignment operator, in MapBase<Derived, 0> (its base class?):

1>eigen\eigen\src/Core/MapBase.h(246): error C2280: 'Eigen::MapBase<Derived,0> &Eigen::MapBase<Derived,0>::operator =(const Eigen::MapBase<Derived,0> &)': attempting to reference a deleted function
1>          with
1>          [
1>              Derived=Eigen::Block<Eigen::Matrix<double,-1,1,0,-1,1>,-1,1,false>
1>          ]
1>  eigen\eigen\src/Core/MapBase.h(174): note: compiler has generated 'Eigen::MapBase<Derived,0>::operator =' here
1>          with
1>          [
1>              Derived=Eigen::Block<Eigen::Matrix<double,-1,1,0,-1,1>,-1,1,false>
1>          ]
Comment 3 Christoph Hertzberg 2014-12-16 18:12:28 UTC
The current version of Macros.h should look like this:
https://bitbucket.org/eigen/eigen/src/1ab289b0ce3f/Eigen/src/Core/util/Macros.h

Please make sure your version is up to date.

The Base::Base problem seems to be related to Bug 821. Try changing that line to:

  typedef Base Base_;
  Base_::Base::operator=(other);
Comment 4 Michael Hofmann 2014-12-17 11:38:21 UTC
Yep, that does the trick.

Changing line 242 in MapBase.h to
  typedef Base Base_;
  Base_::Base::operator=(other);
while at the same time changing line 595 in Macros.h to
  #if EIGEN_COMP_MSVC_STRICT && EIGEN_COMP_MSVC < 1900
fixes this bug.

Note You need to log in before you can comment on or make changes to this bug.