Как реализовать static_cast в C++

Я пытаюсь использовать библиотеку чисел GMP вместе с библиотекой матриц Eigen. Я пытаюсь создать экземпляр шаблона:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

с

Matrix<mpz_class, 3, 3> matrix;

где mpz_class — числовой класс из библиотеки GMP.

Я получаю ошибку компилятора:

 /usr/include/eigen3/Eigen/src/Core/MathFunctions.h:409: error: 
 invalid static_cast from     
 type ‘const __gmp_expr<__mpz_struct [1], __mpz_struct [1]>’ 
 to type ‘int’

Когда я изучаю исходный код библиотеки Eigen, я узнаю, что проблема в том, что mpz_class нельзя преобразовать static_cast в int в этом шаблоне:

template<typename OldType, typename NewType>
struct cast_impl
{
  static inline NewType run(const OldType& x)
  {
    return static_cast<NewType>(x);
  }
};

Как я могу обойти эту проблему? Я знаю, как преобразовать mpz_class в int во время выполнения, но это должен сделать компилятор, так как static_cast — это время компиляции.


person Martin Drozdik    schedule 10.04.2012    source источник


Ответы (3)


Предполагая, что mpz_class безопасен для подкласса, вы можете просто использовать подкласс и написать оператор преобразования:

class your_mpz_class : public mpz_class
{
public:

  // Write public constructors as needed

  operator int()
  {
    return /* Whatever must be returned */;
  }
};
person Gorpik    schedule 10.04.2012
comment
Вы имеете в виду подкласс mpz_class и добавляете этот оператор int()? - person Martin Drozdik; 10.04.2012
comment
О, это было бы действительно хорошим решением. Если предположить, что подкласс mpz_class безопасен, конечно. - person Gorpik; 10.04.2012
comment
Теперь нужно проверить, все ли работает так, как ожидалось. Без знания того, какова польза от этой функции, трудно предвидеть. - person Gorpik; 10.04.2012
comment
Ответ Клейста ниже - это правильно. Добавление класса-оболочки — уродливый кладж. - person Kuba hasn't forgotten Monica; 12.06.2012

Если вы знаете, как это реализовать, вы можете сделать специализацию класса шаблона cast_impl.

template <>
struct cast_impl<Type1, Typ2>
{
    static inline Type2 run(const Type1&x) {
        // Conversion here returning Type2 from Type1
    }
}

Type1 и Type 2 следует заменить фактическими типами в вашей ситуации.

person Kleist    schedule 10.04.2012
comment
Предполагая, что cast_impl содержит только функцию run(), это решение выглядит лучше, чем мое в этом конкретном случае. Конечно, может быть и так, что OP просто указал соответствующую функцию и пропустил остальную часть класса, я не знаю. - person Gorpik; 10.04.2012

В дополнение к другим ответам вы можете прочитать "Eigen: Использование пользовательских скалярных типов" для других требований использования пользовательского скалярного класса, который вы, вероятно, столкнетесь в какой-то момент.

person uesp    schedule 10.04.2012
comment
Благодарю вас! Я натыкаюсь на ошибки одну за другой. Я думаю, что это хорошая идея, чтобы прочитать это в первую очередь. - person Martin Drozdik; 10.04.2012