Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

Ah, now I see. In C++ we would also need to supply template
parameters, but we'd put them before return type
(templatetypename T getResponsePointT); in D we put them
before the colon.

Now I'm trying to write a specialization for Pair. It seems that
this is the way to do it:

Pair!(A, B) getResponse(A, B: Pair!(A, B))(string question)
{
 auto a = getResponse!A( a);
 auto b = getResponse!B( b);
 return new Pair!(A, B)(a, b);
}

auto pair = getResponse!(Pair!(int, int))(pair?);

But it doesn't work: this call resolves to a general version T
getResponse(T), and I get a compilation error because it tries to
instantiate readf!(Pair*).
What am I doing wrong?

On Saturday, 29 November 2014 at 08:06:33 UTC, Ali Çehreli wrote:

On 11/28/2014 10:26 PM, Sly wrote:

 I still don't understand how to
 read this signature:
 Point!T getResponse(T: Point!T)(string question)

The following is what makes sense to me.

Sorry for going step by step but I think it helped me 
understand your question. (See item 3 below.)


1) Point!T is the return type. Although T is unknown at this 
point, we will wait a little because it may be a template 
parameter.


Also, according to the syntax of Point!T, Point is apparently a 
template. So, this function will return the T instantiation of 
Point, whatever T will be deduced to be in a moment.


2) getResponse is the name of the function

3) The first set of parameters is the template parameters:

(T: Point!T)

The meaning: T is a type and this specialization is for Point!T.

Ok, I think I finally understand your original question. I 
agree that it doesn't make sense to say T is a type and this 
specialization is for Point!T. I think we need to read it 
backward in this case: This specialization is for Point!T. If 
so, deduce T from that. So, if getResponse is instantiated 
with Point!int, then T is deduced to be int.


4) The instances of this function template take string 
parameter.


Ali


Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

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:


templatetypename T
struct Reader {
 static T getResponse(const std::string question) {
 std::cout  question  (  typeid(T).name()  ): 
;

 T res;
 std::cin  res;
 return res;
 }
};

templatetypename T
struct Point {
 T x, y;
};

templatetypename T
struct ReaderPointT {
 static PointT getResponse(const std::string question) {
 std::cout  question  \n;
 PointT res;
 res.x = ReaderT::getResponse( x);
 res.y = ReaderT::getResponse( y);
 return res;
 }
};

templatetypename A, typename B
struct Readerstd::pairA, B {
 static std::pairA, B getResponse(const std::string
question) {
 std::cout  question  \n;
 std::pairA, B res;
 res.first = ReaderA::getResponse( first);
 res.second = ReaderB::getResponse( second);
 return res;
 }
};


int main()
{
 int i = Readerint::getResponse(int);
 auto pt = ReaderPointint::getResponse(point);
 auto pair = Readerstd::pairint, 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?


Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

You miss another definition which introduces a conflict:
T getResponse(T)(string question)
{...}

On Saturday, 29 November 2014 at 17:20:42 UTC, Meta wrote:

On Saturday, 29 November 2014 at 11:07:34 UTC, Sly wrote:
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:


Not true, T is inferred based on the the type Point has been 
instantiated with, letting you emit the second template 
argument. The following code works:


struct Point(T)
{
T x;
T y;
}

P getResponse(P: Point!T, T)(string message)
{
return P(T.init, T.init);
}

void main()
{
import std.stdio;

//T is inferred to be int automatically
writeln(getResponse!(Point!int)(test));
}


Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

This is clearly an incorrect way because it requires editing the
original definition every time a new class is introduced.

On Saturday, 29 November 2014 at 19:10:34 UTC, Meta wrote:

On Saturday, 29 November 2014 at 18:19:40 UTC, Sly wrote:

You miss another definition which introduces a conflict:
T getResponse(T)(string question)
{...}


In that case, you're better off with a pair of declarations:

struct Point(T)
{
T x;
T y;
}

T getResponse(T)(string message)
if (!is(T == Point!U, U))
{
return T.init;
}

Point!T getResponse(T)(string message)
if (is(T == Point!U, U))
{
return Point!T(T.init, T.init);
}

void main()
{
auto t = getResponse!int(test);
auto p = getResponse!(Point!int)(test);
}


Re: Can't understand templates

2014-11-29 Thread Sly via Digitalmars-d-learn

OK. I'm using gdc 4.8.2 and this doesn't compile, so it's
probably an old version. Checked on ideone and it works with
dmd-2.042.
Thanks a lot for your help!

On Saturday, 29 November 2014 at 20:16:24 UTC, Ali Çehreli wrote:

On 11/29/2014 10:19 AM, Sly wrote:

 You miss another definition which introduces a conflict:
 T getResponse(T)(string question)
 {...}

The following works with dmd git head:

import std.stdio;

T getResponse(T)(string question)
{
writef(%s (%s): , question, T.stringof);

T response;
readf( %s, response);

return response;
}

class Pair(A, B) {
  A a;
  B b;
  this(A a, B b) {this.a = a; this.b = b;}
}

Pair!(A, B) getResponse(P : Pair!(A, B), A, B)(string question)
{
writeln(question);
 auto a = getResponse!A( a);
 auto b = getResponse!B( b);
 return new Pair!(A, B)(a, b);
}

struct Point(T)
{
T x;
T y;
}

Point!T getResponse(P : Point!T, T)(string question)
{
writefln(%s (Point!%s), question, T.stringof);

auto x = getResponse!T(  x);
auto y = getResponse!T(  y);

return Point!T(x, y);
}

void main()
{
auto number = getResponse!int(number?);
writeln(number);

auto pair = getResponse!(Pair!(int, long))(pair?);
writeln(pair);

auto point = getResponse!(Point!int)(point?);
writeln(point);
}

Ali


Can't understand templates

2014-11-28 Thread Sly via Digitalmars-d-learn

Here is an example from the tutorial:

struct Point(T)
{
  T x;
  T y;
}

T getResponse(T)(string question) {
  writef(%s (%s): , question, T.stringof);
  T response;
  readf( %s, response);
  return response;
}

Point!T getResponse(T: Point!T)(string question) {
  writefln(%s (Point!%s), question, T.stringof);
  auto x = getResponse!T( x);
  auto y = getResponse!T( y);
  return Point!T(x, y);
}

void main()
{
  auto pt = getResponse!(Point!int)(point);
}


I don't understand how to read this signature: Point!T
getResponse(T: Point!T)(string question). Clearly it's not
supposed to be saying that T is subclass of Point!T, so those Ts
must refer to different types. But when I rename it to
getResponse(U: Point!T) I get a compilation error (unknown
identifier T).

Another question: say I have a template class Pair:

class Pair(A, B) {
  A a;
  B b;
  this(A a, B b) {this.a = a; this.b = b;}
}

How to write a specialization for getResponse matching Pair!(A,
B) with any type arguments A and B? I tried this:

T getResponse(T)(string question)
  if (is(T: Pair!(A, B), A, B))
{
  auto a = getResponse!A( a);
  auto b = getResponse!B( b);
  return new Pair!(A, B)(a, b);
}

but get a compile error:

error: d.getResponse called with argument types (string) matches
both:
d.d(19): getResponse(T)(string question)
and:
d.d(40): getResponse(T)(string question) if (is(T : Pair!(A, B),
A, B))


Re: Can't understand templates

2014-11-28 Thread Sly via Digitalmars-d-learn

On Friday, 28 November 2014 at 19:45:48 UTC, H. S. Teoh via
Digitalmars-d-learn wrote:

This syntax is a little confusing, but basically the : there 
is saying
this type, when instantiated with the following pattern, 
produces a

valid type. Essentially it's equivalent to:

Point!T getResponse(T)(string question)
if (is(typeof(Point!T))) // i.e., Point!T is a valid type
{
...
}



Is there a typo here? This version doesn't compile with the
original call: auto pt = getResponse!(Point!int)(point);



Yes, because D does not support overlapping template overloads.


But I thought the original example has ovelapping templates.
Let's take a simpler example from earlier in the tutorial, where
Point is a non-template struct:


// The general definition of the function template (same as
before)
T getResponse(T)(string question)
{
 writef(%s (%s): , question, T.stringof);

 T response;
 readf( %s, response);

 return response;
}

// The specialization of the function template for Point
T getResponse(T : Point)(string question)
{
 writefln(%s (Point), question);

 auto x = getResponse!int(  x);
 auto y = getResponse!int(  y);

 return Point(x, y);
}

auto center = getResponse!Point(Where is the center?);

Doesn't getResponse!Point match both declarations?


Re: Can't understand templates

2014-11-28 Thread Sly via Digitalmars-d-learn

OK, so we *can* have overlapping templates in one fits better
than another, just like in C++. I still don't understand how to
read this signature:
Point!T getResponse(T: Point!T)(string question)


On Friday, 28 November 2014 at 23:59:07 UTC, Ali Çehreli wrote:

On 11/28/2014 12:36 PM, Sly wrote:

 Let's take a simpler example from earlier in the tutorial,
where
 Point is a non-template struct:


 // The general definition of the function template (same as
 before)
 T getResponse(T)(string question)
 {
[...]
 }

That definition would work with any type T. So, it is general: 
it accepts any type.


 // The specialization of the function template for Point
 T getResponse(T : Point)(string question)
 {
[...]
 }

That definition is for T that matches Point (i.e. Point itself 
in this example). So, it is special: it accepts only that type.


 auto center = getResponse!Point(Where is the center?);

 Doesn't getResponse!Point match both declarations?

True but the call is dispatched to the most special of all of 
the matches. It is very briefly explained through a reference 
to C++:


The template picked to instantiate is the one that is most 
specialized that fits the types of the TemplateArgumentList. 
Determine which is more specialized is done the same way as the 
C++ partial ordering rules. If the result is ambiguous, it is 
an error.


See the Specialization heading here:

  http://dlang.org/template.html

Ali