Jump to page: 1 2
Thread overview
Can't use variadic arguments to functions that use templates
Jul 20, 2013
JS
Jul 20, 2013
bearophile
Jul 20, 2013
JS
Jul 20, 2013
JS
Jul 20, 2013
Jesse Phillips
Jul 21, 2013
JS
Jul 22, 2013
Jesse Phillips
Jul 23, 2013
JS
Jul 23, 2013
Jesse Phillips
Jul 23, 2013
JS
Jul 23, 2013
Ali Çehreli
Jul 23, 2013
Jesse Phillips
Jul 23, 2013
H. S. Teoh
Jul 23, 2013
JS
July 20, 2013
variadic parameters are suppose to make life easier but it seems those don't work with templates.

template A(int L) { ... }

void foo(T)(string s, T t...)
{
   A!(t.length);

}

gives error t can't be read at compile time.

I understand in general why this works BUT I will only ever use foo where the number of arguments are known at compile time.

Therefor to get the code to work I have to revert back to the old way of overloading foo many times to emulate variadic parameters.

Essentially all I want to do is to use foo like

foo("a", "b", "c", 'd', s, ...) but the number of arguments is fixed at compile time(almost all arguments are, aren't they?).


Here is a challenge:

Write a function that accepts any number of string or character variables or literals and returns the concatenates them efficiently as possible(as efficient as fixed arguments).

e.g.,

foo1(string s) { return s; }
foo2(string s1, string s2) { return s1~s2; }
etc...

if we had compile time variadic parameters, we could do something like

foo(T t$...) { return mixin(concat!t); } where concat produces the string t[0]~t[1]~t[2]... which produces the same code as the overloaded case, but must simpler.

I don't think this is possible because there is no static version of variadic arguments, i.e., one who's length is always known at compile time.
July 20, 2013
JS:

> variadic parameters are suppose to make life easier but it seems those don't work with templates.
>
> template A(int L) { ... }
>
> void foo(T)(string s, T t...)
> {
>    A!(t.length);
>
> }

Try this:


template A(size_t L) {
    enum A = L;
}

void foo(T...)(string s, T t) {
    auto n = A!(t.length);
}

void main() {
    foo("x", 1, 2);
}


Bye,
bearophile
July 20, 2013
On Saturday, 20 July 2013 at 17:39:59 UTC, bearophile wrote:
> JS:
>
>> variadic parameters are suppose to make life easier but it seems those don't work with templates.
>>
>> template A(int L) { ... }
>>
>> void foo(T)(string s, T t...)
>> {
>>   A!(t.length);
>>
>> }
>
> Try this:
>
>
> template A(size_t L) {
>     enum A = L;
> }
>
> void foo(T...)(string s, T t) {
>     auto n = A!(t.length);
> }
>
> void main() {
>     foo("x", 1, 2);
> }
>
>
> Bye,
> bearophile

;/ I could have swore I tried that ;/

Thanks though! ;)
July 20, 2013
On Saturday, 20 July 2013 at 17:39:59 UTC, bearophile wrote:
> JS:
>
>> variadic parameters are suppose to make life easier but it seems those don't work with templates.
>>
>> template A(int L) { ... }
>>
>> void foo(T)(string s, T t...)
>> {
>>   A!(t.length);
>>
>> }
>
> Try this:
>
>
> template A(size_t L) {
>     enum A = L;
> }
>
> void foo(T...)(string s, T t) {
>     auto n = A!(t.length);
> }
>
> void main() {
>     foo("x", 1, 2);
> }
>
>
> Bye,
> bearophile

is there any way to pass t directly to A?

template A(T...) doesn't seem work nor does using an alias. (or at least, when I try to foreach over it, it doesn't work).


July 20, 2013
On Saturday, 20 July 2013 at 18:27:23 UTC, JS wrote:
> is there any way to pass t directly to A?
>
> template A(T...) doesn't seem work nor does using an alias. (or at least, when I try to foreach over it, it doesn't work).

template A(size_t L) {
    enum A = L;
}

template B(T...) {
void B(T b) {
    import std.stdio;
    foreach(Type; T) {
        pragma(msg, Type.stringof);
    }
    foreach(v; b) {
        writeln(v);
    }
}}

void foo(T...)(string s, T t) {
    auto n = A!(t.length);
    B(t);// t is runtime information
         // T is compile time information
}

void main() {
    foo("x", 1, 2);
}
July 21, 2013
On Saturday, 20 July 2013 at 18:57:18 UTC, Jesse Phillips wrote:
> On Saturday, 20 July 2013 at 18:27:23 UTC, JS wrote:
>> is there any way to pass t directly to A?
>>
>> template A(T...) doesn't seem work nor does using an alias. (or at least, when I try to foreach over it, it doesn't work).
>
> template A(size_t L) {
>     enum A = L;
> }
>
> template B(T...) {
> void B(T b) {
>     import std.stdio;
>     foreach(Type; T) {
>         pragma(msg, Type.stringof);
>     }
>     foreach(v; b) {
>         writeln(v);
>     }
> }}
>
> void foo(T...)(string s, T t) {
>     auto n = A!(t.length);
>     B(t);// t is runtime information
>          // T is compile time information
> }
>
> void main() {
>     foo("x", 1, 2);
> }

I know I tried that but:

import std.cstream, std.stdio;


template B(T...) {
	string B(T b) {
		string s;
		foreach(Type; T) pragma(msg, Type.stringof);
		foreach(v; b) s ~= v.stringof;
		return s;
	}
}

void foo(T...)(T t)
{
    pragma(msg, B(t));
}

void main() {
    foo("x", "a", "b");
	din.getc();
}


does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be.

July 22, 2013
On Sunday, 21 July 2013 at 07:22:08 UTC, JS wrote:
> void foo(T...)(T t)
> {
>     pragma(msg, B(t));
> }
>
> void main() {
>     foo("x", "a", "b");
> 	din.getc();
> }
>
>
> does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be.

My method doesn't make any calls, your foo is a called at runtime. There is no way to observe a function at compile time; ctfeWriteln does not exist.

Also don't stringof variable v (I assume you want the value and not the symbol concatenated.

template B(T...) {
	string B(T b) {
		string s;
		foreach(Type; T) pragma(msg, Type.stringof);
		foreach(v; b) s ~= v;
		return s;
	}
}

string foo(T...)(T t)
{
	return B(t);
}

void main() {
   enum forced = foo("x", "a", "b");
	pragma(msg, forced);
	din.getc();
}
July 23, 2013
On Monday, 22 July 2013 at 16:48:56 UTC, Jesse Phillips wrote:
> On Sunday, 21 July 2013 at 07:22:08 UTC, JS wrote:
>> void foo(T...)(T t)
>> {
>>    pragma(msg, B(t));
>> }
>>
>> void main() {
>>    foo("x", "a", "b");
>> 	din.getc();
>> }
>>
>>
>> does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be.
>
> My method doesn't make any calls, your foo is a called at runtime. There is no way to observe a function at compile time; ctfeWriteln does not exist.
>
> Also don't stringof variable v (I assume you want the value and not the symbol concatenated.
>
> template B(T...) {
> 	string B(T b) {
> 		string s;
> 		foreach(Type; T) pragma(msg, Type.stringof);
> 		foreach(v; b) s ~= v;
> 		return s;
> 	}
> }
>
> string foo(T...)(T t)
> {
> 	return B(t);
> }
>
> void main() {
>    enum forced = foo("x", "a", "b");
> 	pragma(msg, forced);
> 	din.getc();
> }

I don't think you understand(or I've already got confused)...

I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem. Here is a real world example:


template VariadicLoop(T...)
{
	pragma(msg, T);
	string VariadicLoop(T t)
	{
		string s;
		foreach(k; T)
			s ~= k.stringof;
		foreach(v; t)
			s ~= v;
		return s;
	}

	//enum tVariadicLoop = eval();
	//pragma(msg, tVariadicLoop);
}



string join(T...)(string delim, T t)
{
	return mixin(VariadicLoop(t));
}

VariadicLoop should join the strings passed to join(producing whatever code is necessary to do this efficiently.

e.g.,

join(",", "a", s) should result in the code for join:

{

     return "a"~","~s; // s maybe t[1] or something
}

This is the most efficient way to join rather than using a foreach over an array of strings or something or another. (VariadicLoop could handle string[]'s and insert the appropriate code to join them)

The goal I'm trying to solve is efficiently deal with variadic arguments that are compile time calculable along with mixing in the runtime aspect. Basically: get the compiler to do all the work it can before having it done at runtime. if we are passing string literals to join then they can be joined at compile time. If we are passing a combination of string literals, string variables, and string arrays then we deal with each part efficiently as possible.



July 23, 2013
On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:
> I don't think you understand(or I've already got confused)...
>
> I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem.

I'll stick with the reduced example, maybe you can apply it to the real world:

   template B(T...) {
      string B(T b) {
         string s;
         foreach(i, Type; T)
            s ~= Type.stringof ~ " " ~ b[i] ~ ";\n";
         return s;
      }
   }

   void main() {
      enum forced = B("x", "a", "b");
      pragma(msg, forced);
      mixin(forced);
   }
July 23, 2013
On Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote:
> On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:
>> I don't think you understand(or I've already got confused)...
>>
>> I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem.
>
> I'll stick with the reduced example, maybe you can apply it to the real world:
>
>    template B(T...) {
>       string B(T b) {
>          string s;
>          foreach(i, Type; T)
>             s ~= Type.stringof ~ " " ~ b[i] ~ ";\n";
>          return s;
>       }
>    }
>
>    void main() {
>       enum forced = B("x", "a", "b");
>       pragma(msg, forced);
>       mixin(forced);
>    }

What good does that do?

What if I want to use a run-time variable in the mix?

« First   ‹ Prev
1 2