title: Function is ambiguos in c++
body: <p>I'm trying to use a library I found for triangulations, and I'm getting a strange error. When I compile everything, I get the following errors:</p>
  
  <pre><code>'_trytoadd' is ambiguous ' Candidates are: void _trytoadd(Se&lt;SeDcdtVertex,SeDcdtEdge,SeDcdtFace&gt; 
   *, Se&lt;SeDcdtVertex,SeDcdtEdge,SeDcdtFace&gt; *, int, const GsVec2 &amp;, const GsVec2 &amp;, const GsVec2 
   &amp;) '
  </code></pre>
  
  <p>I'm getting this error for _cantpass, _try to add and _ptreeaddent functions, but they are all defined and called properly in this .cpp file. Any idea what's wrong? Here's the code for the class in question:</p>
  
  <pre><code>/*=======================================================================
     Copyright 2010 Marcelo Kallmann. All Rights Reserved.
     This software is distributed for noncommercial use only, without
     any warranties, and provided that all copies contain the full copyright
     notice licence.txt located at the base folder of the distribution. 
    =======================================================================*/
  
  # include &lt;math.h&gt;
  # include &lt;stdlib.h&gt;
  
  # include "gs_geo2.h"
  
  # include "se_lct.h"
  # include "se_triangulator_internal.h"
  
  # define GS_TRACE_ONLY_LINES
  //# define GS_USE_TRACE1 // main search method
  //# define GS_USE_TRACE2 // search expansion
  //# define GS_USE_TRACE3
  # include "gs_trace.h"
  
  //================================================================================
  //========================== search path tree ====================================
  //================================================================================
  
  // nen/nex are the entrance/exit edges of the node being expanded, which is already in the search tree
  // en/ex are the entrance/exit edge of the current traversal being evaluated for expansion
  // (p1,p2) are en coordinates
  bool SeLct::_canpass ( SeDcdtSymEdge* nen, SeDcdtSymEdge* nex, SeDcdtSymEdge* en, SeDcdtSymEdge* ex,
                         const GsPnt2&amp; p1, const GsPnt2&amp; p2, const GsPnt2&amp; p3, float r, float d2 )
   {
     // check if can traverse en/ex traversal:
     if ( _man-&gt;is_constrained(ex-&gt;edg()) ) return false;
  
     // test if next triangle being tested has been already visited:
     if ( _mesh-&gt;marked(en-&gt;fac()) ) return false;
  
     if ( en-&gt;nxt()==ex ) // bot
      { 
        if ( _pre_clearance )
         { float cl = ex-&gt;edg()-&gt;cl(ex);
           if ( cl&lt;d2 ) return false;
         }
        else
         { if ( dist2(p2,p3)&lt;d2 ) return false;
           if ( !_sector_clear(ex-&gt;nxt(),d2,p2,p3,p1) ) return false;
         }
        if ( nex-&gt;fac()==_fi &amp;&amp; nex-&gt;nxt()==nen ) // top-&gt;bot departure transition
         { if ( !_local_transition_free(ex,en,d2,_xi,_yi) ) return false;
         }
      }
     else // top
      {
        if ( _pre_clearance )
         { float cl = en-&gt;edg()-&gt;cl(en);
           if ( cl&lt;d2 ) return false;
         }
        else
         { if ( dist2(p3,p1)&lt;d2 ) return false;
           if ( !_sector_clear(en-&gt;nxt(),d2,p1,p2,p3) ) return false;
         }
        if ( nex-&gt;fac()==_fi &amp;&amp; nen-&gt;nxt()==nex ) // bot-&gt;top departure transition
         { if ( !_local_transition_free(ex,en,d2,_xi,_yi) ) return false;
         }
      }
  
     return true;
   }
  
  // en is the entrance edge, ex the exit edge, (p1,p2) are en coordinates
  void SeLct::_trytoadd ( SeDcdtSymEdge* en, SeDcdtSymEdge* ex, int mi, const GsPnt2&amp; p1, const GsPnt2&amp; p2, const GsPnt2&amp; p3 )
   {
     // verify if it is passable:
     PathNode&amp; n = _ptree-&gt;nodes[mi];
     if ( !_canpass ( (SeDcdtSymEdge*)n.en, (SeDcdtSymEdge*)n.ex, en, ex, p1, p2, p3, _ptree-&gt;radius, _ptree-&gt;diam2 ) ) return;
  
     // ok it is passable, compute cost:
     double x, y;
  
     if ( en-&gt;nxt()==ex )
      _getcostpoint ( &amp;n, n.x, n.y, p2.x, p2.y, p3.x, p3.y, x, y, _ptree-&gt;radius ); // bot
     else
      _getcostpoint ( &amp;n, n.x, n.y, p3.x, p3.y, p1.x, p1.y, x, y, _ptree-&gt;radius ); // top
     // insert:
     # define PTDIST(a,b,c,d) float(sqrt(gs_dist2(a,b,c,d)))
     _ptree-&gt;add_child ( mi, en, ex, n.ncost+PTDIST(n.x,n.y,x,y), PTDIST(x,y,_xg,_yg), x,y ); // A* heuristic
     # undef PTDIST
   }
  
  # define ExpansionNotFinished  -1
  # define ExpansionBlocked      -2
  
  int SeLct::_expand_lowest_cost_leaf ()
   {
     int min_i;
  
     if ( _ptree-&gt;leafs.size()&gt;_maxfronts ) _maxfronts=_ptree-&gt;leafs.size();
  
     min_i = _ptree-&gt;lowest_cost_leaf ();
     GS_TRACE2 ( "Expanding leaf: "&lt;&lt;min_i );
  
     if ( min_i&lt;0 ) return ExpansionBlocked; // no more leafs: path could not be found!
  
     // attention: array references may be invalidated due array reallocation during insertion
     SeDcdtSymEdge* s = (SeDcdtSymEdge*) _ptree-&gt;nodes[min_i].ex-&gt;sym();
     SeDcdtSymEdge* sn = s-&gt;nxt();
     SeDcdtSymEdge* sp = sn-&gt;nxt();
     const GsPnt2&amp; p1 = s-&gt;vtx()-&gt;p; // note: s is in the triangle to expand
     const GsPnt2&amp; p2 = sn-&gt;vtx()-&gt;p;
     const GsPnt2&amp; p3 = sp-&gt;vtx()-&gt;p;
     float d2 = _ptree-&gt;diam2;
  
     // test if next triangle contains goal point:
     if ( gs_in_triangle(p1.x,p1.y,p2.x,p2.y,p3.x,p3.y,_xg,_yg) ) // reached goal triangle !
      { GS_TRACE1 ( "Goal triangle reached..." );
        double r = _ptree-&gt;radius;
        if ( !pt2circfree(this,s,_xg,_yg,r) ) // we do not know if the goal location is valid, so test it now
         { GS_TRACE1 ( "Goal location is invalid." );
           return ExpansionBlocked;
         }
        GS_TRACE1 ( "Goal location valid." );
        GS_TRACE1 ( "Analyzing arrival..." );
        SeDcdtSymEdge* nen = (SeDcdtSymEdge*)_ptree-&gt;nodes[min_i].en;
        SeDcdtSymEdge* nex = (SeDcdtSymEdge*)_ptree-&gt;nodes[min_i].ex;
        _analyze_arrival ( s, 3, r, d2, nen, nex );
        if ( _ent[3].type==EntBlocked )
         { if ( (sn-&gt;edg()-&gt;is_constrained()||dist2(p2,p3)&lt;d2) &amp;&amp;
                (sp-&gt;edg()-&gt;is_constrained()||dist2(p3,p1)&lt;d2) ) 
            { GS_TRACE1 ( "Arrival blocked from all possible entries." );
              return ExpansionBlocked;
            }
           else
            { GS_TRACE1 ( "Arrival is blocked, but search can continue..." );
              // at this point the arrival is not valid but the search will continue, and
              // note that the arrival triangle may still be used as passage so we let
              // the expansion tests in _trytoadd() proceed.
            }
         }
        else
         { GS_TRACE1 ( "Arrival tests passed." );
           GS_TRACE1 ( "Arrival is valid " &lt;&lt; (_ent[3].type==EntTrivial?"and trivial.":"but non trivial.") );
           return min_i; // FOUND!
         }
      }
  
     int nsize = _ptree-&gt;nodes.size();
     _trytoadd ( s, sn, min_i, p1, p2, p3 ); // bot
     _trytoadd ( s, sp, min_i, p1, p2, p3 ); // top
  
     if ( _ptree-&gt;nodes.size()&gt;nsize ) _mesh-&gt;mark ( s-&gt;fac() ); // only mark traversed faces
  
     if (_searchcb) _searchcb(_sudata);
  
     return ExpansionNotFinished; // continue the expansion
   }
  
  void SeLct::_ptreeaddent ( SeDcdtSymEdge* s, bool top, bool edge )
   {
     const GsPnt2&amp; p1 = s-&gt;vtx()-&gt;p;
     const GsPnt2&amp; p2 = s-&gt;nvtx()-&gt;p;
     double x, y;
     if ( edge )
      { x=_xi; y=_yi; }
     else
      { _getcostpoint ( 0, _xi, _yi, p1.x, p1.y, p2.x, p2.y, x, y, _ptree-&gt;radius ); }
  
     // insert:
     # define PTDIST(a,b,c,d) (float)sqrt(gs_dist2(a,b,c,d))
     _ptree-&gt;add_child ( -1, top? s-&gt;nxt():s-&gt;nxn(), s, PTDIST(_xi,_yi,x,y), PTDIST(x,y,_xg,_yg), x, y );
     # undef PTDIST
   }
  
  //================================================================================
  //============================== search path =====================================
  //================================================================================
  
  /* - This is the A* algorithm that takes O(nf), f is the faces in the "expansion frontier". */
  bool SeLct::_search_channel ( double x1, double y1, double x2, double y2, float radius, const SeFace* iniface )
   {
     GS_TRACE1 ( "Starting Search Path..." );
  
     if ( !_ptree ) _ptree = new PathTree;
     _clear_path(); // clear data from previous query and set _path_result to NoPath
  
     _channel.size(0);
     _xi=x1; _yi=y1; _xg=x2; _yg=y2;
  
     if ( !iniface ) return false;
  
     // Even if p1 is on an edge, locate_point will return in s a face that 
     // can be considered to contain p1 (p1 would be invalid if in a vertex)
     SeBase *s;
     LocateResult res=locate_point ( iniface, x1, y1, s );
     if ( res==NotFound )
      { GS_TRACE1 ( "Could not locate first point!" );
        _path_result=NoPath;
        return false;
      }
     _fi = s-&gt;fac(); // save initial face
     if ( !pt1circfree(this,s,x1,y1,radius) ) { _path_result=NoPath; return false; }
  
     // Check if we are to solve trivial or local paths, testing if both points are in the same triangle:
     if ( _man-&gt;in_triangle(s-&gt;vtx(),s-&gt;nxt()-&gt;vtx(),s-&gt;nxn()-&gt;vtx(),x2,y2) )
      { GS_TRACE1 ( "Both points are in the same triangle..." );
        if ( radius==0 )
         { GS_TRACE1 ( "Trivial path returned." );
           _path_result=TrivialPath; return true; // this is it
         }
  
        if ( !pt2circfree(this,s,x2,y2,radius) )
         { GS_TRACE1 ( "Goal point in same triangle invalid. No path returned." );
           _path_result=NoPath; return false;
         }
  
        _path_result = _analyze_local_path ( s, radius );
        if ( _path_result==TrivialPath )
         { GS_TRACE1 ( "Capsule free. Trivial path returned." );
           return true; // path exists
         }
        else if ( _path_result==LocalPath )
         { GS_TRACE1 ( "Deformable capsule is passable. Local path returned." );
           return true; // path exists
         }
        // at this point the result may be a GlobalPath or a NoPath
        GS_TRACE1 ( "Deformable capsule is not passable." );
        // we then let the normal entrance analysis and search to proceed.
        // the entrance that blocked the capsule will also be blocked but
        // there may be a global path to get there so we just do not
        // mark the initial face as visited, allowing it to be found by the global search.   
      }
  
     GS_TRACE1 ( "Searching for a global path..." );
     GS_TRACE1 ( "Analyzing entrances..." );
  
     _analyze_entrances ( s, _xi, _yi, radius );
  
     GS_TRACE1 ( "Entrance 0: "&lt;&lt;(_ent[0].type==EntBlocked?"blocked":_ent[0].type==EntTrivial?"trivial":"not trivial") );
     GS_TRACE1 ( "Entrance 1: "&lt;&lt;(_ent[1].type==EntBlocked?"blocked":_ent[1].type==EntTrivial?"trivial":"not trivial") );
     GS_TRACE1 ( "Entrance 2: "&lt;&lt;(_ent[2].type==EntBlocked?"blocked":_ent[2].type==EntTrivial?"trivial":"not trivial") );
  
     GS_TRACE1 ( "Initializing A* search..." );
     _mesh-&gt;begin_marking ();
     _ptree-&gt;init ( radius );
     if ( _ent[0].type!=EntBlocked ) _ptreeaddent ( _ent[0].s, _ent[0].top, res==EdgeFound? true:false );
     if ( _ent[1].type!=EntBlocked ) _ptreeaddent ( _ent[1].s, _ent[1].top, false );
     if ( _ent[2].type!=EntBlocked ) _ptreeaddent ( _ent[2].s, _ent[2].top, false );
  
     if (_searchcb) _searchcb(_sudata);
  
     GS_TRACE1 ( "Expanding leafs..." );
     int found = ExpansionNotFinished;
     while ( found==ExpansionNotFinished )
      found = _expand_lowest_cost_leaf();
  
     _mesh-&gt;end_marking ();
  
     if ( found==ExpansionBlocked )
      { GS_TRACE1 ( "Points are not connectable!" );
        _path_result = NoPath;
        return false;
      }
  
     _finalsearchnode = found;
     int n = found; // the starting leaf
     s = _ptree-&gt;nodes[n].ex-&gt;sym();
  
     do { _channel.push() = _ptree-&gt;nodes[n].ex;
          n = _ptree-&gt;nodes[n].parent; 
        } while ( n!=-1 );
     _channel.revert();
  
     GS_TRACE1 ( "Path crosses "&lt;&lt;_channel.size()&lt;&lt;" edges." );
  
     _path_result = GlobalPath;
     return true;
   }
  
  void SeLct::get_search_nodes ( GsArray&lt;SeBase*&gt;&amp; e )
   {
     e.size ( 0 );
     for ( int i=0; i&lt;_ptree-&gt;nodes.size(); i++ )
      { e.push() = _ptree-&gt;nodes[i].en;
        e.push() = _ptree-&gt;nodes[i].ex;
      }
   }
  
  int SeLct::get_search_nodes () const
   {
     return _ptree? _ptree-&gt;nodes.size() : 0;
   }
  
  void SeLct::get_search_metric ( GsArray&lt;GsPnt2&gt;&amp; pnts )
   {
     pnts.size ( 0 );
  
     if ( !_ptree ) return;
     for ( int i=0; i&lt;_ptree-&gt;nodes.size(); i++ )
      { 
        PathNode&amp; n = _ptree-&gt;nodes[i];
        if ( n.parent&lt;0 )
         { pnts.push().set ( _xi, _yi ); }
        else
         { PathNode&amp; np = _ptree-&gt;nodes[n.parent];
           pnts.push().set ( np.x, np.y );
         }
        pnts.push().set ( n.x, n.y );
      }
   }
  
  void SeLct::get_search_front ( GsArray&lt;SeBase*&gt;&amp; e )
   {
     e.size ( 0 );
     for ( int i=0; i&lt;_ptree-&gt;leafs.size(); i++ )
      { e.push() = _ptree-&gt;nodes[ _ptree-&gt;leafs.elem(i) ].ex;
      }
   }
  
  //============================ End of File =================================
  </code></pre>