Can't understand templates

Sly via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Nov 29 03:07:34 PST 2014


On Saturday, 29 November 2014 at 09:11:51 UTC, Ali Çehreli wrote:

> Point!T getResponse(P : Point!T, T)(string question)
> {
>     // ...
> }
>

This doesn't work because now this definition has 2 parameters P
and T. I have to specify both like this: auto pt =
getResponse!(Point!int, int)("point");  which of course defeats
the purpose. Otherwise I have ambiguity error:

d.d:73: error: d.getResponse called with argument types (string)
matches both:
	d.d(20): getResponse(T)(string question)
and:
	d.d(31): getResponse(P : Point!T, T)(string question)

Same thing with specialization for Pair.


Actually what I wrote earlier about C++ is wrong because C++
doesn't allow partial specialization for functions. I wrote this
example in C++ using classes:


template<typename T>
struct Reader {
      static T getResponse(const std::string& question) {
          std::cout << question << "(" << typeid(T).name() << "): 
";
          T res;
          std::cin >> res;
          return res;
      }
};

template<typename T>
struct Point {
      T x, y;
};

template<typename T>
struct Reader<Point<T>> {
      static Point<T> getResponse(const std::string& question) {
          std::cout << question << "\n";
          Point<T> res;
          res.x = Reader<T>::getResponse(" x");
          res.y = Reader<T>::getResponse(" y");
          return res;
      }
};

template<typename A, typename B>
struct Reader<std::pair<A, B>> {
      static std::pair<A, B> getResponse(const std::string&
question) {
          std::cout << question << "\n";
          std::pair<A, B> res;
          res.first = Reader<A>::getResponse(" first");
          res.second = Reader<B>::getResponse(" second");
          return res;
      }
};


int main()
{
      int i = Reader<int>::getResponse("int");
      auto pt = Reader<Point<int>>::getResponse("point");
      auto pair = Reader<std::pair<int, int>>::getResponse("pair");

      return 0;
}



I translated it literally into D using your syntax and it worked!


class Reader(T) {
      public static T getResponse(string question) {
          writef("%s (%s): ", question, T.stringof);
          T response;
          readf(" %s", &response);
          return response;
      }
}

class Reader(P: Point!T, T) {
      public static Point!T getResponse(string question) {
          writefln("%s (Point!%s)", question, T.stringof);
          auto x = Reader!T.getResponse(" x");
          auto y = Reader!T.getResponse(" y");
          return Point!T(x, y);
      }
}

class Reader(P: Pair!(A, B), A, B) {
      public static Pair!(A, B) getResponse(string question) {
          writefln("%s (Pair!(%s, %s))", question, A.stringof,
B.stringof);
          auto a = Reader!A.getResponse(" a");
          auto b = Reader!B.getResponse(" b");
          return new Pair!(A, B)(a, b);
      }
}

void main()
{
      auto i = Reader!int.getResponse("int");
      auto pt = Reader!(Point!int).getResponse("point");
      auto pair = Reader!(Pair!(int, int)).getResponse("pair");
}


My questions now are:

1. Apparently D has partial specializations of function
templates, but it uses a weird syntax (T: Point!T). How to extend
this syntax for multiple template parameters? (Basically, how to
write this example without wrapping the function into a class?)

2. Why is there a difference between partial specialization of
function templates and class templates: there's a compilation
error with function templates but not with class templates?


More information about the Digitalmars-d-learn mailing list