Bowen Wen
Bowen Wen

Reputation: 59

When casting Eigen matrix type, error: expected primary-expression before ‘float’

template <typename T>
      bool operator()(const T* parameters, T* residuals) const
    {
        Eigen::Matrix<T, 3, 1> pose(parameters[0],parameters[1],parameters[2]);
        Eigen::Vector3f pose1 = pose.cast<float>();
        Eigen::Affine2f transform = occ->getTransformForState(pose1);  // transform: rotation->translation


        Eigen::Vector3f tmp1 = occ->interpMapValueWithDerivatives(  transform * currPoint);

        Eigen::Matrix<T, 3, 1> transformedPointData(tmp1.cast<T>());  /// {M,dM/dx,dM/dy}

        T funVal = T(1) - transformedPointData[0];

        residuals[0] = funVal;

        return true;
    }

I have a template member function like above. During compilation, it reports

error: expected primary-expression before ‘float’

         Eigen::Vector3f pose1 = pose.cast<float>();

I have to cast to type "float" to make it consistent with "getTransformForState" function's input and output.

I compared with other examples provided by Eigen Library but couldnt find anything wrong.

Any ideas are highly appreciated !

-------------------- update ------------------------

By changing as pose.template cast<float>()

The error is changed as:

/usr/include/eigen3/Eigen/src/Core/MathFunctions.h: In instantiation of ‘static NewType Eigen::internal::cast_impl<OldType, NewType>::run(const OldType&) [with OldType = ceres::Jet<double, 3>; NewType = float]’:
/usr/include/eigen3/Eigen/src/Core/MathFunctions.h:328:44:   required from ‘NewType Eigen::internal::cast(const OldType&) [with OldType = ceres::Jet<double, 3>; NewType = float]’
/usr/include/eigen3/Eigen/src/Core/Functors.h:351:104:   required from ‘const NewType Eigen::internal::scalar_cast_op<Scalar, NewType>::operator()(const Scalar&) const [with Scalar = ceres::Jet<double, 3>; NewType = float]’
/usr/include/eigen3/Eigen/src/Core/CwiseUnaryOp.h:114:75:   required from ‘const Scalar Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::coeff(Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::Index) const [with UnaryOp = Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>; XprType = const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1>; Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::Scalar = float; Eigen::CwiseUnaryOpImpl<UnaryOp, XprType, Eigen::Dense>::Index = long int]’
/usr/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h:495:33:   required from ‘void Eigen::DenseCoeffsBase<Derived, 1>::copyCoeff(Eigen::DenseCoeffsBase<Derived, 1>::Index, const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>, const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1> >; Derived = Eigen::Matrix<float, 3, 1>; Eigen::DenseCoeffsBase<Derived, 1>::Index = long int]’
/usr/include/eigen3/Eigen/src/Core/Assign.h:180:5:   required from ‘static void Eigen::internal::assign_LinearTraversal_CompleteUnrolling<Derived1, Derived2, Index, Stop>::run(Derived1&, const Derived2&) [with Derived1 = Eigen::Matrix<float, 3, 1>; Derived2 = Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>, const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1> >; int Index = 0; int Stop = 3]’
/usr/include/eigen3/Eigen/src/Core/Assign.h:314:21:   [ skipping 5 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/eigen3/Eigen/src/Core/Matrix.h:281:31:   required from ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const Eigen::MatrixBase<OtherDerived>&) [with OtherDerived = Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<ceres::Jet<double, 3>, float>, const Eigen::Matrix<ceres::Jet<double, 3>, 3, 1, 0, 3, 1> >; _Scalar = float; int _Rows = 3; int _Cols = 1; int _Options = 0; int _MaxRows = 3; int _MaxCols = 1]’

Upvotes: 3

Views: 2339

Answers (1)

melpomene
melpomene

Reputation: 85767

The error message means the compiler doesn't know that pose.cast is a template. There are three basic options for what a class member .foo can be:

  1. A value (e.g. a data member or an enum value)
  2. A type name (e.g. something defined with typedef)
  3. A template for one of the above.

In your case, pose is of type Eigen::Matrix<T, 3, 1>. The compiler doesn't yet know what Eigen::Matrix<T, 3, 1> looks like because it depends on what T is (someone could have specialized Eigen::Matrix differently for different types).

So when you access a member of an unknown class (as with pose.cast), the compiler assumes it's option #1 (a value). This leads to it parsing pose.cast < as the beginning of a less-than comparison. The next token (float) triggers an error because the compiler was expecting another value, not a type name.

The fix is to tell the compiler explicitly that .cast is a template:

Eigen::Vector3f pose1 = pose.template cast<float>();

(The fix for case #2 is to use the typename keyword to force interpretation as a type name.)

Upvotes: 8

Related Questions