www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - writef, compile-checked format, pointer

reply novice2 <sorry noem.ail> writes:
format!"fmt"() and writef!"fmt"() templates
with compile-time checked format string
not accept %X for pointers,

but format() and writef() accept it

https://run.dlang.io/is/aQ05Ux
```
void main() {
     import std.stdio: writefln;
     int x;
     writefln("%X", &x);  //ok
     writefln!"%s"(&x);  //ok
     //writefln!"%X"(&x);  //compile error
}
```

is this intentional?
Aug 09 2021
parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:
 format!"fmt"() and writef!"fmt"() templates
 with compile-time checked format string
 not accept %X for pointers,

 but format() and writef() accept it

 https://run.dlang.io/is/aQ05Ux
 ```
 void main() {
     import std.stdio: writefln;
     int x;
     writefln("%X", &x);  //ok
     writefln!"%s"(&x);  //ok
     //writefln!"%X"(&x);  //compile error
 }
 ```

 is this intentional?
Yes. %X is to format integers. Runtime evaluation of a format string does not allow for type checking. When using the template, the evaluation can be thorough and the types can be checked properly. You have 2 solutions for your problem, either a type cast writefln!"%X"(cast(size_t)&x); or using the generic format specifier that will deduce itself the format to using depending in the passed type. writefln!"%s"(&x);
Aug 09 2021
next sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Monday, 9 August 2021 at 22:01:18 UTC, Patrick Schluter wrote:
 On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:
 format!"fmt"() and writef!"fmt"() templates
 with compile-time checked format string
 not accept %X for pointers,

 but format() and writef() accept it

 https://run.dlang.io/is/aQ05Ux
 ```
 void main() {
     import std.stdio: writefln;
     int x;
     writefln("%X", &x);  //ok
     writefln!"%s"(&x);  //ok
     //writefln!"%X"(&x);  //compile error
 }
 ```

 is this intentional?
Yes. %X is to format integers.
It is to format pointers as well, according to the last table on https://dlang.org/phobos/std_format.html. |Type|Format character|Formatted as| |-|-|-| |Pointer| 's' |A null pointer is formatted as 'null'. All other pointers are formatted as hexadecimal numbers with the format character 'X'.| | |'x', 'X' |Formatted as a hexadecimal number.| It looks like a bug to me. — Bastiaan.
Aug 09 2021
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/9/21 3:01 PM, Patrick Schluter wrote:

 On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:
 format!"fmt"() and writef!"fmt"() templates
 with compile-time checked format string
 not accept %X for pointers,

 but format() and writef() accept it

 https://run.dlang.io/is/aQ05Ux
 ```
 void main() {
     import std.stdio: writefln;
     int x;
     writefln("%X", &x);  //ok
     writefln!"%s"(&x);  //ok
     //writefln!"%X"(&x);  //compile error
 }
 ```

 is this intentional?
Yes. %X is to format integers. Runtime evaluation of a format string does not allow for type checking. When using the template, the evaluation can be thorough and the types can be checked properly.
Sensible explanation but it conflicts both with the documentation at https://dlang.org/phobos/std_format.html and the error message for the following: // Intentionally wrong specifier: writefln!"%_"((int*).init); Error: expression `FormatException("Expected one of %s, %x or %X for pointer type.", "/usr/include/dmd/phobos/std/format/internal/write.d", 2990LU, null, null, 0u)` is not constant Both the documentation and the error message suggest %x and %X.
 You
 have 2 solutions for your problem, either a type cast

      writefln!"%X"(cast(size_t)&x);

 or using the generic format specifier that will deduce itself the format
 to using depending in the passed type.

      writefln!"%s"(&x);
That would be my choice but I've just learned that %s prints the null value as "null" instead of hex 0, which may be undesirable in some cases. I think there really is a bug here. I've been hitting a similar bug with some complex range expressions where compile-time checked format strings would not work. I don't know the reason but I suspect a bug in the compile-time checker that involves .init values for arguments. I assume the checker uses .init values to see whether the format expression compiles and works. In fact, the mention of 'null' in the OP's error message makes me think it may be related. Perhaps the un-typed 'null' literal is used somewhere. (?) Ali
Aug 09 2021
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Monday, 9 August 2021 at 22:30:43 UTC, Ali Çehreli wrote:
 I don't know the reason but I suspect a bug in the compile-time 
 checker that involves .init values for arguments.
The compile time checker is pretty bad tbh, it just tries to ctfe execute the given string and sees if it throws. That's kinda clever; the simplest thing that can possibly work, no doubt. But since ctfe cannot work with certain things - like the pointer casts which are done here* - this makes it a bit fragile. And the implementation is really really slow and pretty bloated in codegen too. My personal policy is to never use it. * The compiler probably could special-case `null` at least since that's consistently 0 in D.
 Perhaps the un-typed 'null' literal is used somewhere.
The line is this: const pnum = () trusted { return cast(ulong) p; }(); Which is already blargh code, but in ctfe it is a prohibited operation.
Aug 09 2021
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/9/21 3:46 PM, Adam D Ruppe wrote:

 The compile time checker [...] implementation is really really
 slow and pretty bloated in codegen too.

 My personal policy is to never use it.
My personal policy is to kindly ask you to fix it! :p Ali
Aug 09 2021
prev sibling parent reply nov <sorryno em.ail> writes:
On Monday, 9 August 2021 at 22:30:43 UTC, Ali Çehreli wrote:
 Error: expression `FormatException("Expected one of %s, %x or 
 %X for pointer type.",
i saw this message too, and this is one of reasons of my original question. '%s' bad for pointer in my cases, because result often contains something like "init" or "cast(int*)mytype" i dreamed that programming will be less-error with compile checking format. but reality disappoint :( message for every error in compile-checked format occupy whole screen :( every time i try to use templates, i have problems :(
Aug 09 2021
next sibling parent Tejas <notrealemail gmail.com> writes:
On Tuesday, 10 August 2021 at 05:03:12 UTC, nov wrote:

 every time i try to use templates, i have problems :(
That is why C++ introduced concepts. Wonder when D will be getting them :(
Aug 10 2021
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/9/21 10:03 PM, nov wrote:

 i dreamed that programming will be less-error with compile checking 
format. I still think so because many errors that can be caught at compile time are moved to run time in non-statically-typed languages.
 but reality disappoint :(
 message for every error in compile-checked format occupy whole screen :(
When that happens, I simply change it to runtime-checked format string like you did and it works. (Better would be to identify and fix the problem. Maybe some other time for me...) Ali
Aug 10 2021