Thread overview
How to concatenate a tuple of strings at compile time?
Jan 06, 2018
paul
Jan 06, 2018
user1205
Jan 06, 2018
user1205
Jan 06, 2018
user1205
Jan 06, 2018
user1205
Jan 06, 2018
visitor
Jan 06, 2018
paul
January 06, 2018
Hi!

How to concatenate  a tuple of strings at compile time?

Appending to an enum or an immutable string in a static foreach doesn't work. (And shadowing the thing doesn't work either) a)
Calling a function recursively doesn't work because I had to turn the tuple into an array which cannot be read at compile time. b)

a)
enum/immutable string connected;
static foreach(item; __traits(something))
  connected ~= item;

b)
string concat(string[] a, string b = "", index i = 0)
{
  if (s.length - 1 == index)
  {
     return b ~ a[$-1];
   } else {
     return concat(a,b[index],index+1);
   }
}
concat([__traits(something)]);

An internet search didn't reward any solution but probably I'm just missing something very trivial.
Any clues would be very appreciated. Thanks.

On a different note, what I want to achieve is to automatically generate a function call that hides the fact of a struct being initialized.

something like this:

struct X
{
  int a;
  string b;
}

class C
{
  X _x;

  this(int a, string b)
  {
    _x = X(a, b);
  }
}

January 06, 2018
On Saturday, 6 January 2018 at 19:35:33 UTC, paul wrote:
> Hi!
>
> How to concatenate  a tuple of strings at compile time?
> [...]

Hello, this simple template does the job:

```
template staticCat(T...)
if (T.length)
{
    static if (T.length == 1)
        enum staticCat = T[0];
    else static if (T.length == 2)
        alias staticCat = staticCat!(T[0] ~ T[1]);
    else static if (T.length > 2)
        alias staticCat = staticCat!(T[0] ~ T[1], T[2..$]);
}

enum elems1 = tuple("foo", "bar");
enum elems2 = tuple("0", "1", "2");
enum elems3 = tuple("a");
```

pragma(msg, staticCat!(elems1.expand));
pragma(msg, staticCat!(elems2.expand));
pragma(msg, staticCat!(elems3.expand));

There might be other solutions, maybe even in std.meta.
January 06, 2018
On Saturday, 6 January 2018 at 19:35:33 UTC, paul wrote:
> Hi!
>
> How to concatenate  a tuple of strings at compile time?
>

Something like that maybe ?

import std.stdio;
import std.meta;

enum connected = () {
    auto something = AliasSeq!("one", "two", "three");
    string res = "";
    static foreach(item; something) {{
        res ~= item;
    }}
    return res;
}();

void main()
{
    writefln("connected = %s", connected);
}


January 06, 2018
On Saturday, 6 January 2018 at 21:35:19 UTC, user1205 wrote:
> On Saturday, 6 January 2018 at 19:35:33 UTC, paul wrote:
>> Hi!
>>
>> How to concatenate  a tuple of strings at compile time?
>> [...]
>
> Hello, this simple template does the job:
>
> ```
> template staticCat(T...)
> if (T.length)
> {
>     static if (T.length == 1)
>         enum staticCat = T[0];
>     else static if (T.length == 2)
>         alias staticCat = staticCat!(T[0] ~ T[1]);
>     else static if (T.length > 2)
>         alias staticCat = staticCat!(T[0] ~ T[1], T[2..$]);
> }
>
> enum elems1 = tuple("foo", "bar");
> enum elems2 = tuple("0", "1", "2");
> enum elems3 = tuple("a");
> ```
>
> pragma(msg, staticCat!(elems1.expand));
> pragma(msg, staticCat!(elems2.expand));
> pragma(msg, staticCat!(elems3.expand));
>
> There might be other solutions, maybe even in std.meta.

There is also this one, less verbose, more efficient (not recursive template instances):

```
template staticCat(T...)
if (T.length)
{
    import std.array;
    enum staticCat = [T].join();
}

enum elems1 = tuple("foo", "bar");
enum elems2 = tuple("0", "1", "2");
enum elems3 = tuple("a");

pragma(msg, staticCat!(elems1.expand));
pragma(msg, staticCat!(elems2.expand));
pragma(msg, staticCat!(elems3.expand));
```
January 06, 2018
On Saturday, 6 January 2018 at 21:38:41 UTC, user1205 wrote:
> On Saturday, 6 January 2018 at 21:35:19 UTC, user1205 wrote:
>> On Saturday, 6 January 2018 at 19:35:33 UTC, paul wrote:
>>> Hi!
>>>
>>> How to concatenate  a tuple of strings at compile time?
>>> [...]
>>
>> Hello, this simple template does the job:
>>
>> ```
>> template staticCat(T...)
>> if (T.length)
>> {
>>     static if (T.length == 1)
>>         enum staticCat = T[0];
>>     else static if (T.length == 2)
>>         alias staticCat = staticCat!(T[0] ~ T[1]);
>>     else static if (T.length > 2)
>>         alias staticCat = staticCat!(T[0] ~ T[1], T[2..$]);
>> }
>>
>> enum elems1 = tuple("foo", "bar");
>> enum elems2 = tuple("0", "1", "2");
>> enum elems3 = tuple("a");
>> ```
>>
>> pragma(msg, staticCat!(elems1.expand));
>> pragma(msg, staticCat!(elems2.expand));
>> pragma(msg, staticCat!(elems3.expand));
>>
>> There might be other solutions, maybe even in std.meta.
>
> There is also this one, less verbose, more efficient (not recursive template instances):
>
> ```
> template staticCat(T...)
> if (T.length)
> {
>     import std.array;
>     enum staticCat = [T].join();
> }
>
> enum elems1 = tuple("foo", "bar");
> enum elems2 = tuple("0", "1", "2");
> enum elems3 = tuple("a");
>
> pragma(msg, staticCat!(elems1.expand));
> pragma(msg, staticCat!(elems2.expand));
> pragma(msg, staticCat!(elems3.expand));
> ```

+1

Yeah i upvote myself. Best solution so far.
Maybe tweak the constraint.
January 06, 2018
On Saturday, 6 January 2018 at 21:41:56 UTC, user1205 wrote:
> On Saturday, 6 January 2018 at 21:38:41 UTC, user1205 wrote:
>> On Saturday, 6 January 2018 at 21:35:19 UTC, user1205 wrote:
>>> On Saturday, 6 January 2018 at 19:35:33 UTC, paul wrote:
>>>> Hi!
>>>>
>>>> How to concatenate  a tuple of strings at compile time?
>>>> [...]
>> ```
>> template staticCat(T...)
>> if (T.length)
>> {
>>     import std.array;
>>     enum staticCat = [T].join();
>> }
>>
>> enum elems1 = tuple("foo", "bar");
>> enum elems2 = tuple("0", "1", "2");
>> enum elems3 = tuple("a");
>>
>> pragma(msg, staticCat!(elems1.expand));
>> pragma(msg, staticCat!(elems2.expand));
>> pragma(msg, staticCat!(elems3.expand));
>> ```
>
> +1
>
> Yeah i upvote myself. Best solution so far.
> Maybe tweak the constraint.

BTW rule of thumb: when you have the choice between template metaprogramming and CTFE use CTFE, it's faster. The solution based on std.array.join is CTFE.
January 06, 2018
Thanks for the input.

Unfortunately I still can't convince the compiler. __traits allMembers includes functions. Trying to filter those with std.traits.isCallable, it complains about strings that can't be read or fields that can't be accessed at compile time. Affected are both solutions.

So any insight in why mixin(fullyQualifiedName!T ~ "." ~ item) produces a compiler error saying that string can't be accessed at compile time would be very appreciated.

Same goes for [tuple(..)].filter!(item => !isCallable!(mixin(fullyQualifiedName!T ~ "." ~ item))).join;