Thread overview
Serialization/deserialization of templated class
Jun 28, 2017
Eugene Wissner
Jun 28, 2017
Eugene Wissner
Jun 28, 2017
Jacob Carlborg
June 28, 2017
Hi, guys!

I have templated classes like this:

class Some(T1) {
  T1 value;
  this(T1 _value){
    value = _value;
  }
}
class Pair(T1, T2) {
  T1 first;
  T2 second;
  this(T1 _first, T2 _second){
    first = _first;
    second = _second;
  }
}

and a lot of serialised data, which I have to read and instantiate into given classes.
Serialized data looks like this: 'Some(Pair("df", 5.0))' or 'Pair(Some(true), 11)', i.e. order of structs, its types and inclusion order are unknown at compile time.

I know there are several serialisation libraries, but I found they work only with non-templated classes, like:

class Foo {
  int a;
}

I can read input data and parse it, but have no idea how to construct object of templated class in this situation. Please give a hint.

June 28, 2017
On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:
> Hi, guys!
>
> I have templated classes like this:
>
> class Some(T1) {
>   T1 value;
>   this(T1 _value){
>     value = _value;
>   }
> }
> class Pair(T1, T2) {
>   T1 first;
>   T2 second;
>   this(T1 _first, T2 _second){
>     first = _first;
>     second = _second;
>   }
> }
>
> and a lot of serialised data, which I have to read and instantiate into given classes.
> Serialized data looks like this: 'Some(Pair("df", 5.0))' or 'Pair(Some(true), 11)', i.e. order of structs, its types and inclusion order are unknown at compile time.
>
> I know there are several serialisation libraries, but I found they work only with non-templated classes, like:
>
> class Foo {
>   int a;
> }
>
> I can read input data and parse it, but have no idea how to construct object of templated class in this situation. Please give a hint.

Templates are a compile time feature. You won't be able to initialize the classes if you don't know the type at compile time.

You can use some data structure like Variant that can save values of different types.
You could use union for data storage in you class and list all possible types as union members.
Probably if you have serialized data, you convert strings to other types, so it may be possible to perfom if-checks:
if (myDataIsStringAndDouble(data))
{
  auto var = new Some!(Pair!(string, double))(new Pair!(string, double)("df", 5.0));
}
else if (myDataIsStringAndInt(data))
{
  auto var = new Some!(Pair!(string, int))(new Pair!(string, int)("df", 5));
}
June 28, 2017
On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
> On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:


> Probably if you have serialized data, you convert strings to other types, so it may be possible to perfom if-checks:
> if (myDataIsStringAndDouble(data))
> {
>   auto var = new Some!(Pair!(string, double))(new Pair!(string, double)("df", 5.0));
> }
> else if (myDataIsStringAndInt(data))
> {
>   auto var = new Some!(Pair!(string, int))(new Pair!(string, int)("df", 5));
> }

It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here.

I got the Variant idea, I'll give it a try.
From other point of view, is there a reflection, say

auto i = newInstance("Pair!(int, string)(10, \"asdf\")"),

something like in Java?
June 28, 2017
On Wednesday, 28 June 2017 at 05:52:38 UTC, Dmitry Solomennikov wrote:
> On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
>> On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:
>
>
>> Probably if you have serialized data, you convert strings to other types, so it may be possible to perfom if-checks:
>> if (myDataIsStringAndDouble(data))
>> {
>>   auto var = new Some!(Pair!(string, double))(new Pair!(string, double)("df", 5.0));
>> }
>> else if (myDataIsStringAndInt(data))
>> {
>>   auto var = new Some!(Pair!(string, int))(new Pair!(string, int)("df", 5));
>> }
>
> It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here.
>
> I got the Variant idea, I'll give it a try.
> From other point of view, is there a reflection, say
>
> auto i = newInstance("Pair!(int, string)(10, \"asdf\")"),
>
> something like in Java?

As far as I know, Java can modify the byte code at runtime. D is a compiled language. It has good compile-time reflection. Anyway you have to find a way to initialize the classes with the types you need. If the type isn't initialized at compile-time, it isn't just there at runtime and can't be used.
June 28, 2017
On 2017-06-28 07:52, Dmitry Solomennikov wrote:
> On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
>> On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:
>
>
>> Probably if you have serialized data, you convert strings to other
>> types, so it may be possible to perfom if-checks:
>> if (myDataIsStringAndDouble(data))
>> {
>>   auto var = new Some!(Pair!(string, double))(new Pair!(string,
>> double)("df", 5.0));
>> }
>> else if (myDataIsStringAndInt(data))
>> {
>>   auto var = new Some!(Pair!(string, int))(new Pair!(string,
>> int)("df", 5));
>> }
>
> It is possible, but it is not a general solution. I've posted couple of
> sample classes, but there are more complicated cases, of course, and it
> well be combinatorial explosion here.
>
> I got the Variant idea, I'll give it a try.
>  From other point of view, is there a reflection, say
>
> auto i = newInstance("Pair!(int, string)(10, \"asdf\")"),
>
> something like in Java?

It's possible to instantiate classes using reflection in D, but not for templated classes:

class Foo(T) {}
class Bar {}

void main()
{
    Foo!int a = new Foo!int;
    Bar b = new Bar;

    auto o1 = Object.factory("main.Foo!int.Foo"); // does not work for templated classes
    auto o2 = Object.factory("main.Bar"); // works for non-templated classes

    assert(o1 is null);
    assert(o2 !is null);
}

Actually, if you have the template instantiation available you can do this:

Object o = Foo!int.classinfo.create();

-- 
/Jacob Carlborg
June 29, 2017
On 6/28/17 1:52 AM, Dmitry Solomennikov wrote:
> On Wednesday, 28 June 2017 at 05:01:17 UTC, Eugene Wissner wrote:
>> On Wednesday, 28 June 2017 at 04:41:25 UTC, Dmitry Solomennikov wrote:
> 
> 
>> Probably if you have serialized data, you convert strings to other types, so it may be possible to perfom if-checks:
>> if (myDataIsStringAndDouble(data))
>> {
>>   auto var = new Some!(Pair!(string, double))(new Pair!(string, double)("df", 5.0));
>> }
>> else if (myDataIsStringAndInt(data))
>> {
>>   auto var = new Some!(Pair!(string, int))(new Pair!(string, int)("df", 5));
>> }
> 
> It is possible, but it is not a general solution. I've posted couple of sample classes, but there are more complicated cases, of course, and it well be combinatorial explosion here.
> 
> I got the Variant idea, I'll give it a try.
>  From other point of view, is there a reflection, say
> 
> auto i = newInstance("Pair!(int, string)(10, \"asdf\")"),

No, because the class itself doesn't eixst until you instantiate it.

Certainly if you want to write out all the possible instantiations, it's possible, via the mechanisms already specified above. What I would do is create a newInstance *template* that takes a string and generates a function that would build it from that string. Then you can feed a sample file that contains all the possible instantiations to it at *compile time* (via import strings), and then you can automatically build the code that would be able to parse it. Finally, send the real file at runtime.

> something like in Java?

It's important to realize that Java's generics are completely different than D's templates. They are a compile-time wrapping around a runtime construct. Of course, it's possible to mimic Java, but you won't get templates out of it, more like Variant holders.

-Steve