Skip to content

Commit

Permalink
Add template keyword to fix dependent name errors
Browse files Browse the repository at this point in the history
Clang and GCC complained about this, and it's indeed needed (see e.g. https://eigen.tuxfamily.org/dox/TopicTemplateKeyword.html). MSVC accepts it without template keyword, but it's non-standard C++.
Basically, the object that we call the templated function on (head<>() or cast<>()) is itself a templated type. Because we don't know at compile time what that first templated type is, the compiler can't know what the function is that we call on it (i.e. it could be a type or operator<()). So we need the "template" keyword to tell the compiler that it's a templated function.

One way to avoid this would be to declare a template at namespace scope, like std::tuple: It has an associated get function template that is declared in the std namespace instead of being a class member, so we can do std::get<i>(t) instead of t.template get<i>(). However, that's not really a good solution here I think. There's also nothing wrong with using `template` here, it just makes the code a bit more difficult to read.
  • Loading branch information
patrikhuber committed Mar 27, 2023
1 parent b4f89ce commit e5f8a6b
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
26 changes: 16 additions & 10 deletions include/eos/fitting/ceres_nonlinear.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ struct PerspectiveProjectionLandmarkCost
Eigen::Map<const Eigen::Vector3<T>> translation(camera_translation);

Eigen::Matrix4<T> model_view_mtx = Eigen::Matrix4<T>::Identity();
model_view_mtx.block<3, 3>(0, 0) = rotation.toRotationMatrix();
model_view_mtx.col(3).head<3>() = translation;
model_view_mtx.template block<3, 3>(0, 0) = rotation.toRotationMatrix(); // dependent name
model_view_mtx.col(3).template head<3>() = translation; // dependent name

// Todo: use get_opencv_viewport() from nonlin_cam_esti.hpp.
const Eigen::Vector4<T> viewport(T(0), T(image_height), T(image_width),
Expand Down Expand Up @@ -296,8 +296,8 @@ struct VertexColorCost
Eigen::Map<const Eigen::Vector3<T>> translation(camera_translation);

Eigen::Matrix4<T> model_view_mtx = Eigen::Matrix4<T>::Identity();
model_view_mtx.block<3, 3>(0, 0) = rotation.toRotationMatrix();
model_view_mtx.col(3).head<3>() = translation;
model_view_mtx.template block<3, 3>(0, 0) = rotation.toRotationMatrix(); // dependent name
model_view_mtx.col(3).template head<3>() = translation; // dependent name

// Todo: use get_opencv_viewport() from nonlin_cam_esti.hpp.
const Eigen::Vector4<T> viewport(T(0), T(image.height()), T(image.width()),
Expand Down Expand Up @@ -385,9 +385,12 @@ Eigen::Vector3<T> get_shape_at_point(const eos::morphablemodel::PcaModel& shape_
{
// Computing Shape = mean + shape_basis*shape_coeffs + blendshapes*blendshape_coeffs:
const Eigen::Vector3f mean = shape_model.get_mean_at_point(vertex_id);
const Eigen::Vector3<T> shape_vector =
shape_model.get_rescaled_pca_basis_at_point(vertex_id).leftCols(shape_coeffs.size()).cast<T>() *
shape_coeffs;
// Note: We seem to have a dependent name here, so we need 'template', to help the compiler that 'cast<T>'
// is a template.
const Eigen::Vector3<T> shape_vector = shape_model.get_rescaled_pca_basis_at_point(vertex_id)
.leftCols(shape_coeffs.size())
.template cast<T>() *
shape_coeffs;
Eigen::Vector3<T> expression_vector(T(0.0), T(0.0), T(0.0));
for (std::size_t i = 0; i < blendshape_coeffs.size(); i++)
{
Expand All @@ -412,9 +415,12 @@ Eigen::Vector3<T> get_vertex_color_at_point(const eos::morphablemodel::PcaModel&
Eigen::Map<const Eigen::VectorX<T>> color_coeffs)
{
const Eigen::Vector3f mean = color_model.get_mean_at_point(vertex_id);
const Eigen::Vector3<T> color_vector =
color_model.get_rescaled_pca_basis_at_point(vertex_id).leftCols(color_coeffs.size()).cast<T>() *
color_coeffs;
// Note: We seem to have a dependent name here, so we need 'template', to help the compiler that 'cast<T>'
// is a template.
const Eigen::Vector3<T> color_vector = color_model.get_rescaled_pca_basis_at_point(vertex_id)
.leftCols(color_coeffs.size())
.template cast<T>() *
color_coeffs;

return Eigen::Vector3<T>(mean.cast<T>() + color_vector);
};
Expand Down
6 changes: 5 additions & 1 deletion include/eos/render/matrix_projection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ Eigen::Vector3<T> project(const Eigen::Vector3<T>& point_3d, const Eigen::Matrix
projected_point.x() = projected_point.x() * T(viewport(2)) + T(viewport(0));
projected_point.y() = projected_point.y() * T(viewport(3)) + T(viewport(1));

return projected_point.head<3>();
// Note: We need the 'template' keyword, as we have a dependent name - 'T' is unknown when the compiler
// parses this expression, so we need to tell it that 'head<3>()' is a template function (and not e.g. an
// 'operator<' or something like that). We could alternatively rewrite this as:
// 'return Eigen::Vector3<T>(projected_point.x(), projected_point.y(), projected_point.z());'
return projected_point.template head<3>();
};

} /* namespace render */
Expand Down

0 comments on commit e5f8a6b

Please sign in to comment.