samedi 16 mai 2020

C++11: Syntax for calling a method template?

I am having trouble with finding the right syntax for a method template. The following code is a simplified test case to show the problem.

A C++11 class template with a method template search.

#include <functional> // std::less
#include <cstring> // std::strcmp

template<class T, typename _Compare = std::less<T>>
class XTree
{
public:
      class Node;
      typedef T value_type;
      typedef _Compare value_compare;

      class Node
      {
          friend XTree;
      public:
          int data_ = 0;
          T t_;
          Node (T const& t) : t_(t) {}
      }; // Node

      Node *root_ = nullptr;

      XTree() {}
      ~XTree() { }

public:

      template<class S, class V>
      const Node* search (V const& val) const
      {
          S const& s = S();
          int star = root_ ? s (root_->t_, val) : 1;
          return star == 0 ? root_ : nullptr;
      }

      template<class S, class V>
      Node* search (V const& val)
      {
          return const_cast<Node*> (((const XTree*) this)->search<S,V>
(val));
      }
};

Let's test the above template with some Xtype. All works fine.

struct Xtype
{
      const char *id_;
      int x_;
      bool operator < (Xtype const& y) const
      {
          return id_ < y.id_;
      }
};

Xtype* test ()
{
      using T = XTree<Xtype>;
      T t;

      // First template param for T::search<> ()
      struct XSearch
      {
          int operator () (T::value_type const& v, int const& x) const
          {
              return v.x_ - x;
          }
      };

      // Ok, this compiles and works as expected.
      T::Node *n = t.search<XSearch, int> (123);
      return n ? & n->t_ : nullptr;
}

Now let's try XTree::search in a more complicated context...

template<bool b> struct _xMapIdType;
template<> struct _xMapIdType<true> { typedef char* type; };
template<> struct _xMapIdType<false> { typedef const char* type; };


template<class T, bool copy_id>
class XMap
{
public:
      struct Element;
      typedef XTree<Element> Tree;
      typedef typename Tree::Node Node;

      typedef typename _xMapIdType<copy_id>::type IdType;

      // This is Tree::value_type.
      struct Element
      {
          IdType const id_;
          Node* node_ = nullptr;
          T t_;

          Element () {}
          Element (IdType const& id, T const& t) : id_(id), t_(t) {}

          // How 2 Tree::value_type's compare.
          bool operator < (Element const& x) const
          {
              return std::strcmp (id_, x.id_) < 0;
          }

          // For 1nd template argument of Tree::search<> ().
          struct Search
          {
              int operator () (Element const& e, IdType const& id) const
              {
                  return std::strcmp (e.id_, id);
              }
          };
      };

      Tree tree_;

      // Now try to use Tree::search.

      auto find (IdType id) const -> typename Tree::Node*
      {
          /* <-- Line 126 */
          return tree_.search<typename Element::Search, IdType> (id);
      }
};


int main ()
{
      using M = XMap<const char*, false>;

      M m;

      auto n = m.find ("Hallo");
      return n != nullptr;
}

The last line of find throws errors that are not very specific, and I am stuck.

a.cpp:127:53: error: expected '(' before ',' token
a.cpp:127:61: error: expected primary-expression before '>' token
a.cpp: In member function 'typename XMap<T, copy_id>::Tree::Node*
XMap<T, copy_id>::find(XMap<T, copy_id>::IdType) const [with T = const
char*; bool copy_id = false; typename XMap<T, copy_id>::Tree::Node =
XTree<XMap<const char*, false>::Element, std::less<XMap<const char*,
false>::Element> >::Node; XMap<T, copy_id>::IdType = const char*]':
a.cpp:128:5: warning: control reaches end of non-void function
[-Wreturn-type]

Aucun commentaire:

Enregistrer un commentaire