определяемое пользователем преобразование не может использовать static_cast в C++

Я пытаюсь решить некоторые проблемы с Eigen. В процессе я обнаружил, что static_cast и определяемое пользователем преобразование конфликтуют. Возможно, проблема вызвана std::enable_if?

Вот в основном то, что я пробовал:

#include <Eigen/Dense>
#include <bits/stdc++.h>

using namespace std;

class Vector2
{
public:
    operator Eigen::Vector2d ()
    {   
        return data;
    }   
private:
    Eigen::Vector2d data;
};

class Box2
{
public:
    void Extend(const Vector2 & a)  
    {   
        data.extend( static_cast<Eigen::Vector2d>(a) );     // error, but why?
    }   
private:
    Eigen::AlignedBox2d data;   
};

int main()
{
    Vector2 a;
    Eigen::Vector2d b = a;      // ok, implicit conversion
    return 0;   
}

g++ -std=c++11выводит много логов ошибок, это последняя часть:

eigen/eigen/Eigen/src/Core/PlainObjectBase.h:863:30: note:   template argument deduction/substitution failed:
eigen/eigen/Eigen/src/Core/PlainObjectBase.h: In substitution of ‘template<class T> void Eigen::PlainObjectBase<Derived>::_init1(const Index&, typename Eigen::internal::enable_if<((((((! Eigen::internal::is_same<long int, typename Eigen::internal::traits<T>::Scalar>::value) && Eigen::internal::is_same<long int, T>::value) && (typename Eigen::internal::dense_xpr_base<Derived>::type:: SizeAtCompileTime != Eigen::Dynamic)) && (typename Eigen::internal::dense_xpr_base<Derived>::type:: SizeAtCompileTime != 1)) && Eigen::internal::is_convertible<T, typename Eigen::internal::traits<T>::Scalar>::value) && Eigen::internal::is_same<typename Eigen::internal::traits<T>::XprKind, Eigen::ArrayXpr>::value), T*>::type*) [with T = T; Derived = Eigen::Matrix<double, 2, 1>] [with T = Vector2]’:
eigen/eigen/Eigen/src/Core/Matrix.h:296:33:   required from ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T&) [with T = Vector2; _Scalar = double; int _Rows = 2; int _Cols = 1; int _Options = 0; int _MaxRows = 2; int _MaxCols = 1]’
test.cpp:21:52:   required from here
eigen/eigen/Eigen/src/Core/PlainObjectBase.h:863:30: error: invalid use of incomplete type ‘struct Eigen::internal::enable_if<false, Vector2*>’
In file included from eigen/eigen/Eigen/Core:364:0,
                 from eigen/eigen/Eigen/Dense:1,
                 from eigen/eigen/Eigen/Eigen:1,
                 from test.cpp:2:
eigen/eigen/Eigen/src/Core/util/Meta.h:162:50: error: declaration of ‘struct Eigen::internal::enable_if<false, Vector2*>’
 template<bool Condition, typename T=void> struct enable_if;
                                                  ^

Похоже на проблему с enable_if, интересно, почему static_cast не работает. Есть ли способ решить эту проблему, не изменяя Eigen? Это нормально сделать сейчас:

void Extend(Vector2 a)  
{   
    Eigen::Vector2d b = a;
    data.extend( b );    
} 

Но это слишком некрасиво.


person sfire    schedule 11.09.2018    source источник


Ответы (1)


Похоже проблема enable_if, интересно почему static_cast не работает.

Это не имеет ничего общего с самим static_cast. Ошибка возникает из-за того, что operator Eigen::Vector2d () Vector2 не определено для объектов const, а поскольку ваш Box2::Extend() принимает const Vector2& a, соответствующее приведение не определено для этой строки в коде. Добавьте const версию определяемого пользователем приведения Vector2 в Eigen::Vector2d, чтобы он компилировался и сохранял const-correctity кода:

const operator Eigen::Vector2d () const
{   
    return data;
} 

Теперь использование работает так, как вы хотели:

int main()
{
    Vector2 a;
    Eigen::Vector2d b = a;    // ok, implicit conversion

    Box2 boxy;
    boxy.Extend(a);           // also ok, implicit conversion inside, from a const&

    return 0;   
}
person Geezer    schedule 11.09.2018
comment
@SkepticalEmpiricist Спасибо! Я последовал вашему решению и решил его. Журналы ошибок компиляции C++ часто вводят меня в заблуждение. Также поблагодарите других здесь. - person sfire; 11.09.2018
comment
@sfire Обратите внимание, что, если подумать, я отредактировал, чтобы прояснить, что правильным решением является добавить еще одну версию оператора приведения, а не просто изменить существующую. - person Geezer; 12.09.2018
comment
Хорошо, я знаю. Спасибо за вашу информацию о корректности const. - person sfire; 12.09.2018