Search code examples
c++templatescgaltypename

Issue with templated Kernel for Efficient Ransac


I am trying to use the efficient Ransac algorithm of CGAL in a function using a templated Kernel, here is a minimal code to reproduce.

#include <CGAL/property_map.h>
#include <CGAL/Point_with_normal_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Shape_detection/Efficient_RANSAC.h>
// Type declarations.
typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;


template < typename K > //comment for working version
void funcTest() {

//typedef   CGAL::Exact_predicates_inexact_constructions_kernel  K;       //uncomment for working version
  typedef   std::tuple<typename K::Point_3,typename K::Vector_3, size_t, bool>     Point_and_normals;
  typedef   CGAL::Nth_of_tuple_property_map<0, Point_and_normals>  Point_map;
  typedef   CGAL::Nth_of_tuple_property_map<1, Point_and_normals>  Normal_map;
  typedef   CGAL::Shape_detection::Efficient_RANSAC_traits
                <K, std::vector<Point_and_normals>, Point_map, Normal_map>             TraitsShape;
  typedef  CGAL::Shape_detection::Efficient_RANSAC<TraitsShape> Efficient_ransac;
  typedef  CGAL::Shape_detection::Plane<TraitsShape> PlaneRansac;

  std::vector<Point_and_normals>  points;
  Efficient_ransac ransac;
  ransac.set_input(points);
  ransac.add_shape_factory<PlaneRansac>();
  ransac.detect();
}

int main (int argc, char** argv) {

  funcTest<Kernel>();   //comment for working version
  //funcTest());        //uncomment for working version
  return 0;
}

In this code the templated version doesn't build giving this error

tester.cpp:24:39: error: expected primary-expression before ‘>’ token
    24 |   ransac.add_shape_factory<PlaneRansac>();
       |                                       ^
tester.cpp:24:41: error: expected primary-expression before ‘)’ token
    24 |   ransac.add_shape_factory<PlaneRansac>();

However the issue is not present with the explicit Kernel, my guess is it may come from a typename issue, but I am not sure of what I may be doing wrong on this one. Any advice, recommandation is welcome


Solution

  • The problem is that the compiler doesn't know that whether the token < that follows the add_shape_factory is a less-than-operator or a beginning of a template argument list.

    We can use the .template construct when calling the member function template to solve this problem as shown below:

    ransac.template add_shape_factory<PlaneRansac>();
    //-----^^^^^^^^------------------------------------->added template keyword here to indicate that it is a member function template
    

    The .template is used to tell the compiler that the < token is the beginning of the template argument list and not less-than-operator.