mbsim-env / fmatvec

A fast vector/matrix library
https://www.mbsim-env.de
GNU Lesser General Public License v2.1
10 stars 5 forks source link

MSVC compile error C3066: there are multiple ways ... and "and" #6

Closed GreenGary closed 4 years ago

GreenGary commented 4 years ago

Trying to get #5 done, I spotted an interesting, not trivial compile(er) error. Only MSVC (in all versions) complains about this, gcc and clang have no problem.

Problem: linear_algebra_double.cc(782) and linear_algebra_double.cc(891) raise error C3066. The called function operator()(const Range<Var,Var> &I) const is declared both in class Vector<Ref,AT> and Matrix<General,Ref,Ref,AT> (with different return types). Vector derived from Matrix. Both functions are not virtual. The root cause is the using Matrix<General, Ref, Ref, AT>::operator(); in vector.h, which pulls function name operator() into Vector. MSVC now complains about multiple possible ways that an object of this type can be called with these arguments... I am not convinced, that this is really a bug in MSVC. Anyway, this should be fixed (for MSVC or in general)

Potential Fix:

#ifdef _MSC_VER
      AT* operator()() { return Matrix<General, Ref, Ref, AT>::operator()(); }
      const AT* operator()() const { return Matrix<General, Ref, Ref, AT>::operator()(); }
#else
      using Matrix<General, Ref, Ref, AT>::operator();
#endif

Here is a reproducer that can be used to play around e.g. with godbolt or whatever platofrm

template <class Type, class Row, class Col, class XT>
class TestA {};

template <class XT>
class TestA<float, float, float, XT>
{
public:
  float operator()(const int &I) const { return 1.0f; }
};

template <class XT>
class TestB : public TestA<float, float, float, XT>
{
public:
  double operator()(const int &I) const { return 1.0; }
  using TestA<float, float, float, XT>::operator();
};

void failMSVC(int num) {
    TestB<double> b;
    b(2);
}
rolandzander commented 4 years ago

@friedrichatgc : please do comment on GreenGary's potential fix. I am by dimensions not firm enough in both fmatvec and C++ to judge.

friedrichatgc commented 4 years ago

"inline const Vector<Ref,AT> operator()(const Range<Var,Var> &I) const;" in vector.h:281 and "inline const SquareMatrix<Ref,AT> operator()(const Range<Var,Var> &I) const;" in general_matrix.h:348 really have the same signature but different return types as noted by the error message.

According to https://en.cppreference.com/w/cpp/language/using_declaration regarding "using": "If the name is the name of an overloaded member function of the base class, all base class member functions with that name are introduced." the using statement brings in all operator()(......) overloads. And the next sentence "If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class" means that this seems to be a MSVC bug.

I checked all overloads of operator()(...) in matrix. Only operator()() is useful in vector. So I think the "using" statement is valid according to c++ but to much here. Hence your proposed fix is good and should replace the "using" statement not only for MSVC but also for gcc. Added a wrapper for other overloads is not needed.

GreenGary commented 4 years ago

https://developercommunity.visualstudio.com/content/problem/975389/false-c3306-with-using-in-class.html

GreenGary commented 4 years ago

Microsoft support found a workaround: "Swapping the order of the using declaration and the overloaded operator appears to be a workaround."

GreenGary commented 4 years ago

Fixed