Thread overview
Creating Tuple or AliasSeq
Apr 07, 2017
ANtlord
Apr 07, 2017
Ali Çehreli
Apr 07, 2017
ANtlord
Apr 07, 2017
ANtlord
Apr 08, 2017
Graham Fawcett
April 07, 2017
Hello! I've got an issue related to making a Tuple or AliasSeq using income template arguments. I want to create template makes an array of objects from array of arrays have different sizes and different types of values.

I created temporary solution. It is a concatenation of strings that will be passed to mixin.

But I just want to reorder parameters and pass them to ObjectType using AliasSeq or Tuple. Does it possible?

import std.stdio;

template objectFactory(ObjectType, Args...)
{
	static string loopGen() {
		string code = (ObjectType[]).stringof ~ " res = []; ";
		foreach(i, _; Args)
		{
			enum level = to!string(i);
			code ~= "foreach(elem" ~ level ~ "; Args[" ~ level ~ "])";
		}

		code ~= "res ~= " ~ ObjectType.stringof ~ "(";

		foreach(i, _; Args)
		{
			enum level = to!string(i);
			code ~= "elem" ~ level;

			static if(i + 1 < Args.length)
			{
				code ~= ", ";
			}
		}
		code ~= ");";

		return code;
	}

	static ObjectType[] factory()
	in {
		static assert(Args.length > 0);
		foreach(argumentCases; Args)
			static assert(argumentCases.length > 0);
	}
	body
	{
		enum codeString = loopGen();
		mixin(codeString);
		return res;
	}

	alias objectFactory = factory;
}

Example:

struct Pair {
	int number;
	string name;
}

auto pairKit = objectFactory!(Pair, [1], ["qwe", "asd"]);
auto pairSet = pairKit();
assert(pairSet.length == 2);
writeln(pairSet[0]); // writes Pair(1, "qwe");
writeln(pairSet[1]); // writes Pair(1, "asd");

Thanks. Sorry if my english is not clear.
April 07, 2017
On 04/06/2017 10:43 PM, ANtlord wrote:
> Hello! I've got an issue related to making a Tuple or AliasSeq using
> income template arguments. I want to create template makes an array of
> objects from array of arrays have different sizes and different types of
> values.

Here is a solution:

auto objectFactory(ObjectType, Args...)(Args args) {
    import std.algorithm : cartesianProduct, map;
    import std.array : array;

    return cartesianProduct(args).map!(a => ObjectType(a.expand)).array;
}

struct Pair {
    int number;
    string name;
}

import std.stdio;

void main() {
    auto pairKit = objectFactory!(Pair)([1, 2], ["qwe", "asd"]);
    auto pairSet = pairKit;
    writeln(pairSet);
}

Ali

April 07, 2017
On Friday, 7 April 2017 at 07:46:40 UTC, Ali Çehreli wrote:
>
> Here is a solution:
>
> auto objectFactory(ObjectType, Args...)(Args args) {
>     import std.algorithm : cartesianProduct, map;
>     import std.array : array;
>
>     return cartesianProduct(args).map!(a => ObjectType(a.expand)).array;
> }
>
> struct Pair {
>     int number;
>     string name;
> }
>
> import std.stdio;
>
> void main() {
>     auto pairKit = objectFactory!(Pair)([1, 2], ["qwe", "asd"]);
>     auto pairSet = pairKit;
>     writeln(pairSet);
> }
>
> Ali

It's great! Thanks a lot!
April 07, 2017
On Friday, 7 April 2017 at 07:46:40 UTC, Ali Çehreli wrote:
>
> Here is a solution:
>
> auto objectFactory(ObjectType, Args...)(Args args) {
>     import std.algorithm : cartesianProduct, map;
>     import std.array : array;
>
>     return cartesianProduct(args).map!(a => ObjectType(a.expand)).array;
> }
>
> struct Pair {
>     int number;
>     string name;
> }
>
> import std.stdio;
>
> void main() {
>     auto pairKit = objectFactory!(Pair)([1, 2], ["qwe", "asd"]);
>     auto pairSet = pairKit;
>     writeln(pairSet);
> }
>
> Ali

I can't understand. Documentation of cartesianProduct points out about finite arrays. At least one of arrays must be a inifinte array. As far as I know finite arrays is `int[3]` and infinite is `int[]` (https://dlang.org/library/std/range/primitives/is_infinite.html). Am I right?

If I am then I can't understand why DMD return error about finite ranges compiling following code.

	struct Hay {
		int a;
		@disable this(this);
		@disable this();
		this(int a){
			this.a = a;
		}
		
	}
	Hay[] params = [ Hay(1), Hay(23) ];
	auto products = cartesianProduct(params, params);

Error text:

> static assert  "cartesianProduct involving finite ranges must have at least one finite forward range"

I noticed that removing disabling default constructors helps. Does that mean an array contains objects of a struct with disabled default constructor is finite?


April 08, 2017
On Friday, 7 April 2017 at 10:26:24 UTC, ANtlord wrote:
> On Friday, 7 April 2017 at 07:46:40 UTC, Ali Çehreli wrote:
>> [...]
>
> I can't understand. Documentation of cartesianProduct points out about finite arrays. At least one of arrays must be a inifinte array. As far as I know finite arrays is `int[3]` and infinite is `int[]` (https://dlang.org/library/std/range/primitives/is_infinite.html). Am I right?
>
> If I am then I can't understand why DMD return error about finite ranges compiling following code.
>
> 	struct Hay {
> 		int a;
> 		@disable this(this);
> 		@disable this();
> 		this(int a){
> 			this.a = a;
> 		}
> 		
> 	}
> 	Hay[] params = [ Hay(1), Hay(23) ];
> 	auto products = cartesianProduct(params, params);
>
> Error text:
>
>> [...]
>
> I noticed that removing disabling default constructors helps. Does that mean an array contains objects of a struct with disabled default constructor is finite?

No, int[] is a finite array. isInfinite is meant to test for ranges which are statically defined to *never* be empty, no matter how many times you consume them. See std.range.repeat(T) for an example of such a range.