Thread overview
static foreach / How to construct concatenated string?
Mar 07, 2020
Robert M. Münch
Mar 07, 2020
Adam D. Ruppe
Mar 07, 2020
Robert M. Münch
Mar 07, 2020
MoonlightSentinel
Mar 08, 2020
Robert M. Münch
Mar 08, 2020
Robert M. Münch
Mar 09, 2020
MoonlightSentinel
Mar 09, 2020
Timon Gehr
March 07, 2020
I want to create a "CREATE TABLE data (...)" where the columns are derived from struct member names. Something like:

string s = "CREATE TABLE data(";

static foreach(f; FieldNameTuple!myStruct) {
 s ~= f ~ ",";
}

s ~= ");";

Which of course doesn't work... I didn't find any reference how to build-up strings in a statif foreach loop.

Is this possible at all?

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

March 07, 2020
On Saturday, 7 March 2020 at 16:30:59 UTC, Robert M. Münch wrote:
> Which of course doesn't work... I didn't find any reference how to build-up strings in a statif foreach loop.
>
> Is this possible at all?

Use regular foreach with a regular string. Put that inside a function.

Then simply use that function to initialize your other thing and enjoy the magic of CTFE!
March 07, 2020
On Saturday, 7 March 2020 at 16:30:59 UTC, Robert M. Münch wrote:
> Is this possible at all?

You can use an anonymous lambda to build the string in CTFE:

------------------------------------------

struct S {
    int a;
    bool b;
}

import std;

enum string sql = {
    string s = "CREATE TABLE data(";

    static foreach(f; FieldNameTuple!S) {
    	s ~= f ~ ",";
    }

	s ~= ");";
    return s;
} ();

pragma(msg, sql);

------------------------------------------

This prints "CREATE TABLE data(a, b);"

March 07, 2020
On 2020-03-07 16:40:15 +0000, Adam D. Ruppe said:

> Use regular foreach with a regular string. Put that inside a function.
> 
> Then simply use that function to initialize your other thing and enjoy the magic of CTFE!

Perfect! This implicit CTFE is a tricky thing to see/remember/... Feeling a bit dumb but, hey it works :-)

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

March 08, 2020
On 2020-03-07 16:41:47 +0000, MoonlightSentinel said:

> On Saturday, 7 March 2020 at 16:30:59 UTC, Robert M. Münch wrote:
>> Is this possible at all?
> 
> You can use an anonymous lambda to build the string in CTFE:
> 
> ------------------------------------------
> 
> struct S {
>      int a;
>      bool b;
> }
> 
> import std;
> 
> enum string sql = {
>      string s = "CREATE TABLE data(";
> 
>      static foreach(f; FieldNameTuple!S) {
>      	s ~= f ~ ",";
>      }
> 
> 	s ~= ");";
>      return s;
> } ();
> 
> pragma(msg, sql);
> 
> ------------------------------------------
> 
> This prints "CREATE TABLE data(a, b);"

Nice... is the enum a so called "manifest constant" for which the initializer is evaluated at compile time?

OT: The pragma seems to print the string twice... at least here on my side.

OT2: Looks like I have to read through the language spec again... and most likely over and over again, to have all these tricks at my finger-tips.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

March 08, 2020
On 2020-03-07 16:41:47 +0000, MoonlightSentinel said:

> You can use an anonymous lambda to build the string in CTFE:
> 
> ------------------------------------------
> 
> struct S {
>      int a;
>      bool b;
> }
> 
> import std;
> 
> enum string sql = {
>      string s = "CREATE TABLE data(";
> 
>      static foreach(f; FieldNameTuple!S) {
>      	s ~= f ~ ",";
>      }
> 
> 	s ~= ");";
>      return s;
> } ();
> 
> pragma(msg, sql);
> 
> ------------------------------------------
> 
> This prints "CREATE TABLE data(a, b);"

You can get rid of the enum und the static and it will work too.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

March 09, 2020
On 07.03.20 17:41, MoonlightSentinel wrote:
> On Saturday, 7 March 2020 at 16:30:59 UTC, Robert M. Münch wrote:
>> Is this possible at all?
> 
> You can use an anonymous lambda to build the string in CTFE:

It turns out that if you do use this standard idiom, you might end up getting blamed for an unrelated DMD bug though:
https://github.com/dlang/dmd/pull/9922

:o)
March 09, 2020
On Sunday, 8 March 2020 at 20:28:01 UTC, Robert M. Münch wrote:
> You can get rid of the enum [...]

That depends on your use case. You will need enum if you want to use the value at compile time (e.g. when using it as a template parameter). Otherwise a normal string will suffice.

> und the static and it will work too.

Yesh, I forgot about the old implicit static foreach loop.