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?

Reply via email to