Jump to page: 1 2
Thread overview
How to properly use variadic templates (functions)?
Dec 20, 2021
rempas
Dec 20, 2021
Adam D Ruppe
Dec 21, 2021
rempas
Dec 20, 2021
russhy
Dec 21, 2021
rempas
Dec 21, 2021
Anonymouse
Dec 21, 2021
rempas
Dec 21, 2021
vit
Dec 21, 2021
rempas
Dec 21, 2021
russhy
Dec 21, 2021
rempas
Dec 21, 2021
Stanislav Blinov
Dec 21, 2021
russhy
Dec 22, 2021
rempas
Dec 22, 2021
eugene
Dec 21, 2021
rempas
December 20, 2021

I'm trying to implement "printf" and I'm getting an error. The smallest possible code to demonstrate the error is:

import core.stdc.stdio;

void print(T...)(string prompt, T args) {
  // Suppose all 'args' are of type "string" for this example
  ulong carg = 0;
  for (ulong i = 0; i < args[carg].length; i++) {
    putc(args[carg][i], stdout);
  }
}

void main() {
  print("Prompt (ignored)", "Hello", " world!\n");
}

The error output I'm getting is:

test.d(6): Error: variable `carg` cannot be read at compile time
test.d(7): Error: variable `carg` cannot be read at compile time
test.d(12): Error: template instance `test.print!(string, string)` error instantiating

There is another error in my original code. Let's see the following line:

u64 str_len = strlen(args[carg]); //u64 = ulong

Now this should also give me the error that the variable "carg" cannot be read at compile time (which it probably does as it gives me an error when trying to use "str_len" inside a "for loop") but instead it gives me the following error:

Error: function `core.stdc.string.strlen(scope const(char*) s)` is not callable using argument types `(string)`
       cannot pass argument `_param_1` of type `string` to parameter `scope const(char*) s`

Any ideas?

December 20, 2021
On Monday, 20 December 2021 at 21:26:45 UTC, rempas wrote:
>   // Suppose all 'args' are of type "string" for this example

still use

foreach(arg; args)

and skip that index variable.
December 20, 2021

Here how i'd do, but i'm not sure how to keep track of the index of the arguments, i forgot..

import core.stdc.stdio: putc, stdout;

void print(T...)(string prompt, T args)
{
    foreach (a; args)
    {
        alias A = typeof(a);

        static if (is(A : string))
        {
            for (int j = 0; j < a.length; j++)
            {
                putc(a[j], stdout);
            }
        }
        else
        {
            // handle your other types
            print("", A.stringof);
        }
    }

}

void main()
{
    print("Prompt (ignored)", "Hello", " world!\n", 123);
}
December 21, 2021
On Monday, 20 December 2021 at 21:49:59 UTC, Adam D Ruppe wrote:
>
> still use
>
> foreach(arg; args)
>
> and skip that index variable.

I know I can use foreach ("static foreach" more specifically) but I need to be able to get the index to choose a specific argument because I want to do formatting (that's why I said "printf")
December 21, 2021

On Monday, 20 December 2021 at 22:02:02 UTC, russhy wrote:

>

Here how i'd do, but i'm not sure how to keep track of the index of the arguments, i forgot..

import core.stdc.stdio: putc, stdout;

void print(T...)(string prompt, T args)
{
    foreach (a; args)
    {
        alias A = typeof(a);

        static if (is(A : string))
        {
            for (int j = 0; j < a.length; j++)
            {
                putc(a[j], stdout);
            }
        }
        else
        {
            // handle your other types
            print("", A.stringof);
        }
    }

}

void main()
{
    print("Prompt (ignored)", "Hello", " world!\n", 123);
}

This will not do for me because I want to do formatted output and I need the index. But thanks a lot for tying to help!

December 21, 2021

On Tuesday, 21 December 2021 at 06:44:36 UTC, rempas wrote:

>

This will not do for me because I want to do formatted output and I need the index. But thanks a lot for tying to help!

I'm not certain I understand, but won't foreach (i, a; args) { /* ... */ } in his example do that?

As in, if you necessarily must index args instead of using a foreach variable,

import core.stdc.stdio : putc, stdout;

void print(T...)(string prompt, T args)
{
    foreach (i, a; args)
    {
        alias A = typeof(args[i]);

        static if (is(A : string))
        {
            for (int j = 0; j < args[i].length; j++)
            {
                putc(args[i][j], stdout);
            }
        }
        else
        {
            // handle your other types
            print("", A.stringof);
        }
    }
}

void main()
{
    print("Prompt (ignored)", "Hello", " world!\n", 123);
}
December 21, 2021

On Tuesday, 21 December 2021 at 08:11:39 UTC, Anonymouse wrote:

>

I'm not certain I understand, but won't foreach (i, a; args) { /* ... */ } in his example do that?

As in, if you necessarily must index args instead of using a foreach variable,

import core.stdc.stdio : putc, stdout;

void print(T...)(string prompt, T args)
{
    foreach (i, a; args)
    {
        alias A = typeof(args[i]);

        static if (is(A : string))
        {
            for (int j = 0; j < args[i].length; j++)
            {
                putc(args[i][j], stdout);
            }
        }
        else
        {
            // handle your other types
            print("", A.stringof);
        }
    }
}

void main()
{
    print("Prompt (ignored)", "Hello", " world!\n", 123);
}

No it will not. I will try to explain it the best way I can. When I say I want to index args, I mean that I want to index and choose which argument to use rather than use them continuously one after another inside a foreach. For example check the following call:

print("Hello %s!%c", "world", '\n');

In that case I want to first print print from "H" up to (but not include) "%s". Then I want to print the first argument. After that, I want to print the '!' character and then I want to print the second argument. So I need a way to keep track which argument was the last one I printed and manually choose which argument to use. So foreach will not do in that case because I don't want to continuously use the arguments one after another. Is is more clear now? "writef" exists in phobos so I'm pretty sure that there is a way to do that.

December 21, 2021

On Tuesday, 21 December 2021 at 08:26:17 UTC, rempas wrote:

>

On Tuesday, 21 December 2021 at 08:11:39 UTC, Anonymouse wrote:

>

I'm not certain I understand, but won't foreach (i, a; args) { /* ... */ } in his example do that?

As in, if you necessarily must index args instead of using a foreach variable,

import core.stdc.stdio : putc, stdout;

void print(T...)(string prompt, T args)
{
    foreach (i, a; args)
    {
        alias A = typeof(args[i]);

        static if (is(A : string))
        {
            for (int j = 0; j < args[i].length; j++)
            {
                putc(args[i][j], stdout);
            }
        }
        else
        {
            // handle your other types
            print("", A.stringof);
        }
    }
}

void main()
{
    print("Prompt (ignored)", "Hello", " world!\n", 123);
}

No it will not. I will try to explain it the best way I can. When I say I want to index args, I mean that I want to index and choose which argument to use rather than use them continuously one after another inside a foreach. For example check the following call:

print("Hello %s!%c", "world", '\n');

In that case I want to first print print from "H" up to (but not include) "%s". Then I want to print the first argument. After that, I want to print the '!' character and then I want to print the second argument. So I need a way to keep track which argument was the last one I printed and manually choose which argument to use. So foreach will not do in that case because I don't want to continuously use the arguments one after another. Is is more clear now? "writef" exists in phobos so I'm pretty sure that there is a way to do that.

You can use switch + static foreach:

import std.stdio;

    //this print args in reverse order:
    void print(T...)(string prompt, T args)
    {
        void print_arg(size_t index){
            switch(index){
                static foreach(i, a; args){
                	case i:
                        // handle your other types
                        write(a);
                    	return;	
                }
                default:
                	assert(0, "no impl");
            }
        }

        write(prompt);
        size_t len = args.length;
        while(len --> 0)
            print_arg(len);
    }

    void main(){
        print("Prompt (ignored): ", "Hello", " world!\n", 123);
    }

December 21, 2021

On Tuesday, 21 December 2021 at 08:42:35 UTC, vit wrote:

>

You can use switch + static foreach:

import std.stdio;

    //this print args in reverse order:
    void print(T...)(string prompt, T args)
    {
        void print_arg(size_t index){
            switch(index){
                static foreach(i, a; args){
                	case i:
                        // handle your other types
                        write(a);
                    	return;	
                }
                default:
                	assert(0, "no impl");
            }
        }

        write(prompt);
        size_t len = args.length;
        while(len --> 0)
            print_arg(len);
    }

    void main(){
        print("Prompt (ignored): ", "Hello", " world!\n", 123);
    }

Cool! That's probably what I wanted to do! It seems that when looping inside a "static foreach" and taking the index, then I can compare it with a value that is not calculated at compile time. This way I can also check for the type of the variables and do my original plan which will make the function even better! Thanks a lot for the help dude!!!

December 21, 2021

Please keep us updated, that'll be interesting to see how a pure D printf would look like!

« First   ‹ Prev
1 2