Thread overview
Using std.conv.to with std.typecons.Typedef
Jan 11, 2016
Saurabh Das
Jan 11, 2016
Tobi G.
Jan 11, 2016
Saurabh Das
Jan 11, 2016
Tobi G.
Jan 11, 2016
Saurabh Das
January 11, 2016
I am trying to create 2 types which contain integral values but should not be compatible with each other. std.typecons.Typedef seems perfect for this:

alias QuestionId = Typedef!(long, long.init, "QuestionId");
alias StudentId = Typedef!(long, long.init, "StudentId");

However I'm failing to use using std.conv.to:
QuestionId q = to!QuestionId("34"); <-- gives compile errors

(This is a reduced example, the actual use case is to use std.csv to read in a structure from file, which in turn calls to!xyz)

How can I get std.conv to understand std.typecons.Typedef? In general, is there a better solution to orthogonal types than Typedef?

Thanks,
Saurabh

January 11, 2016
On Monday, 11 January 2016 at 08:03:19 UTC, Saurabh Das wrote:
>
> How can I get std.conv to understand std.typecons.Typedef?

You can do something like this:

QuestionId q = to!(TypedefType!QuestionId)("43");

> In general, is there a better solution to orthogonal types than Typedef?

Typedef is a reasonably solution, for this in my opinion.

togrue

January 11, 2016
On Monday, 11 January 2016 at 12:01:30 UTC, Tobi G. wrote:
> On Monday, 11 January 2016 at 08:03:19 UTC, Saurabh Das wrote:
>>
>> How can I get std.conv to understand std.typecons.Typedef?
>
> You can do something like this:
>
> QuestionId q = to!(TypedefType!QuestionId)("43");
>
>> In general, is there a better solution to orthogonal types than Typedef?
>
> Typedef is a reasonably solution, for this in my opinion.
>
> togrue

Oh excellent. Yes that works for a standalone conversion.  Do you know how I can use this with std.csv?

import std.typecons;
alias QuestionId = Typedef!(long, long.init, "QuestionId");
alias StudentId = Typedef!(long, long.init, "StudentId");

struct MyStuff
{
    QuestionId q;
    StudentId s;
}

void main()
{
    import std.csv, std.stdio, std.algorithm, std.range;
    File("file.csv").byLine.joiner("\n").csvReader!(MyStuff)(null).array;
}

This doesn't work. But if MyStuff is defined as: struct MyStuff { int q, s; }, then it works.

Any ideas?


January 11, 2016
On Monday, 11 January 2016 at 12:15:55 UTC, Saurabh Das wrote:
>
> Any ideas?

Yes. Because Typedef is introducing new Types, which csvReader doesn't know what they are,
you'll need a little workaround and cast the values yourself.

import std.csv, std.stdio, std.algorithm, std.range;

enum csvTxt = "10, 20
30, 40
50, 50";

myStuff = csvTxt.csvReader!(Tuple!(long, long))
	.map!(a => MyStuff(cast(QuestionId)a[0], cast(StudentId) a[1]))
        .array;


The .map does nothing other as getting the information out of the Tuple 'a' and constructing a struct of the type MyStuff.

togrue
January 11, 2016
On Monday, 11 January 2016 at 12:59:05 UTC, Tobi G. wrote:
> On Monday, 11 January 2016 at 12:15:55 UTC, Saurabh Das wrote:
>>
>> Any ideas?
>
> Yes. Because Typedef is introducing new Types, which csvReader doesn't know what they are,
> you'll need a little workaround and cast the values yourself.
>
> import std.csv, std.stdio, std.algorithm, std.range;
>
> enum csvTxt = "10, 20
> 30, 40
> 50, 50";
>
> myStuff = csvTxt.csvReader!(Tuple!(long, long))
> 	.map!(a => MyStuff(cast(QuestionId)a[0], cast(StudentId) a[1]))
>         .array;
>
>
> The .map does nothing other as getting the information out of the Tuple 'a' and constructing a struct of the type MyStuff.
>
> togrue

Yes that does make sense. I could read in a POD struct and convert it to a typed one.

Though I was hoping for a more elegant solution... This'll have to do I guess.

Thanks!