On Monday, 17 December 2012 at 12:04:30 UTC, Pavel wrote:
On Monday, 17 December 2012 at 11:03:01 UTC, Simen Kjaeraas wrote:
On 2012-42-17 11:12, Pavel <[email protected]> wrote:

Either I do not understand the work of this feature or it is an obvious bug:

import std.stdio;
import std.conv;

void main()
{
enum string expr = "DMD compiles this garbage ... iiiii - \" #### $$$";
        
  enum bool bTest = __traits(compiles, expr);
  enum bool bTest2 = __traits(compiles, "int i = q{};");
                
  writeln("bTest: " ~ to!string(bTest));
  writeln("bTest2: " ~ to!string(bTest2));
}

Produces (tested with dmd32 2.060 and dmd32 2.059):
 bTest: true
 bTest2: true

(http://dpaste.dzfl.pl/5d338ab3)

Could you please somebody explain this?

Thanks,
Pavel

Let's start off with the obligatory 'You're doing it wrong'.

__traits(compiles, ...) does not check the content of strings.
If you want that, use mixin("somestring").

What your code does is simply check if the string is one that
could be embedded in D code, which both of them can.

If instead of using strings you do this:

  enum bool bTest2 = __traits(compiles, {int i = q{};});

You will see that the result is false.


Nice hint with __traits(compiles, { <statements> }) - thanks!
(Because as I've now read in documentation the __traits(compiles) does not accepts statements directly.)

Because when writing templates with operating code as strings it is easy to forget that __traits(compiles, ...) behaves so I suppose it is useful to create a utility template for it:

template Compiles(string code)
{
enum bool Compiles = __traits(compiles, mixin("{" ~ code ~ "}"));
}

void main()
{
   enum string code1 = "int i = q{};";
   enum string code2 = "int i = 5; i++;";
        
writeln("Compiles `" ~ code1 ~ "`: " ~ to!string(Compiles!code1)); writeln("Compiles `" ~ code2 ~ "`: " ~ to!string(Compiles!code2));
}

Oops, bad idea - it will work only for self-contained code but will not work when code references some variables from current scope.

Reply via email to