www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - better assertions and __FILE__

reply Bruce Adams <tortoise_74 nospam.ya.hoo.co.mapson.uk> writes:
Hi,
    Another FAQ item I couldn't find. I'm looking to implement some wrappers
around assert as assert is too primative and doesn't give me enough
information. I want to go down the xUnit path E.g.

in the code:
   assertEqual(foo,bar);

leading to output:
   Equality assertion failed in file.cpp at line 10
   Expected Value: 10
   Actual Value: 5

I got as far as:

void assertEqual(Type)(Type actual_, 
                                Type expected_, 
		            char[] file_, 
		            uint line_) {
   if (actual_ != expected_) {
      writefln("Equality assertion failed");
      writefln("actual:   '", actual_, "'");
      writefln("expected: '", expected_, "'");
      _d_assert(file_,line_);
   }
}

This lets me use:

   assertEqual!(string)("foo","bar",cast(char[])(__FILE__),__LINE__);

Where I'm having trouble is getting __FILE__ and __LINE__ added (presumably
using a mixin) so I can avoid the cruft.

As a side issue how do I get string constants implicitly converted to
char[] or better yet string.
In my example above

   assertEqual("foo","bar",cast(char[])(__FILE__),__LINE__);

also works but only because "foo".length == "bar".length

   // broken!
   assertEqual("foo","bar2",cast(char[])(__FILE__),__LINE__);

Final question to prove I'm a noob. In std.asserterror shouldn't 

 _d_assert(char[] file_,uint line_);

actually be:

 _d_assert(string file_,uint line_);

Regards,

Bruce.
Aug 15 2007
next sibling parent reply Bruce Adams <ifyoudontknowmebynow searchdaweb.com> writes:
Bruce Adams Wrote:

 
 Hi,
     Another FAQ item I couldn't find. I'm looking to implement some wrappers
around assert as assert is too primative and doesn't give me enough
information. I want to go down the xUnit path E.g.
 
 in the code:
    assertEqual(foo,bar);
 
 leading to output:
    Equality assertion failed in file.cpp at line 10
    Expected Value: 10
    Actual Value: 5
 
 I got as far as:
 
 void assertEqual(Type)(Type actual_, 
                                 Type expected_, 
 		            char[] file_, 
 		            uint line_) {
    if (actual_ != expected_) {
       writefln("Equality assertion failed");
       writefln("actual:   '", actual_, "'");
       writefln("expected: '", expected_, "'");
       _d_assert(file_,line_);
    }
 }
 
 This lets me use:
 
    assertEqual!(string)("foo","bar",cast(char[])(__FILE__),__LINE__);
 
 Where I'm having trouble is getting __FILE__ and __LINE__ added (presumably
using a mixin) so I can avoid the cruft.
 
Here are a few more things I've learned on my travels around the various D web-pages. __FILE__ & __LINE__ are expanded by the tokeniser not the parser. This implies that they would not be available for use in mixins as they will already have been expanded. This is confirmed with a quick test. So what I'm trying to do is not currently possible. I have seen two proposals for improvements to D bandied around. 1) "context" functions // does not exist void context(__line, __file) assertEqual(int a, int b) { if (a != b) { writefln("equality assertion failed"); writefln("expected: ",a); writefln("actual: ",b); _d_assert(__line,__file); } } 2) Access to the call stack through "trace" something like: import std.trace; // does not exist yet void assertEqual(int a, int b) { if (a != b) { writefln("equality assertion failed"); writefln("expected: ",a); writefln("actual: ",b); StackFrame callerFrame = getStack().up(); uint callingLine = callerFrame.getLine(); char[] callingFile = callerFrame.getFile(); _d_assert(callingLine, callingFile); } } I think the latter has more appeal and more support. You can use it for generating stack traces and core dumps for example. However, I have no idea of what status these ideas are at. There's nothing in the issue tracking system. I'm not sure if that's the right place for frivolous feature requests. Has anyone heard anything on the grapevine? Are there language development roadmap and feature request pages knocking around the web somewhere that I've yet to find? Regards, Bruce.
Aug 16 2007
next sibling parent Bruce Adams <ifyoudontknowmebynow searchdaweb.com> writes:
I have given in and raised this as an issue:

http://d.puremagic.com/issues/show_bug.cgi?id=1425

duplicated below for discussion purposes:

For improved support for assertions, logging code and stack traces it would be
useful to have means of identifying the calling frame of reference. This would
also have the advantage of rendering __LINE__ and its ilk redundant.
For example it is not currently possible to implement a cppunit like
assertEqual function.
The best I can achieve is:

void assertEqual(Type)(Type actual_, Type expected_, 
                       char[] file_, 
                       uint line_) {
   if (actual_ != expected_) {
      writefln("Equality assertion failed");
      writefln("actual:   '", actual_, "'");
      writefln("expected: '", expected_, "'");
   }
   _d_assert(file_,line_);
}

Which has to be used as:

assertEqual!(string)("foo","bar",cast(char[])(__FILE__),__LINE__);

It should be possible to achieve a more natural syntax like:

assertEqual("foo","bar");

Several proposals seem have been made on the newsgroups but none has been
raised as a request here.
I personally think the best approach is to have a library function

stackFrame[] callStack = std.trace();

By default the calling frame would be something like:

class stackFrame {
   stackFrame* parent;
   object[]    arguments;
}

When functions request source identification the compiler would have to
include mapping information so its not a pure library issue.
E.g

class SourceStackFrame: public StackFrame {
// inherited
//   stackFrame* parent;
//   object[]    arguments;
   uint        parentLine;
   string*     parentFile;
   string*     parentFunction;   
}

I imagine two ways of creating such a structure.
Use of an analogue to __FILE__ e.g. the so called "context" keyword
would tell the compiler to use the special stack frame for a specific call
only.
A command line switch could tell the compiler to always use the source stack
frame format - with resulting code bloat.
Aug 16 2007
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Bruce Adams wrote:
 
 Here are a few more things I've learned on my travels around the various D
web-pages.
 
 __FILE__ & __LINE__ are expanded by the tokeniser not the parser. This implies
that they would not be available for use in mixins as they will already have
been expanded. This is confirmed with a quick test. So what I'm trying to do is
not currently possible.
It's possible to use CTFE with string mixins to achieve this. I have whipped up something quick, ugly as hell but could be improved using std.metastrings.Format: char[] assertEqual(char[] actual, char[] expected) { return `if (` ~ actual ~ `!=` ~ expected ~ `) { ` `writefln("Equality assertion failed in " ~ __FILE__ ~ " at line " ~ std.metastrings.ToString!(__LINE__));` `writefln("expected value: '", ` ~ expected ~ `, "'");` `writefln("actual value: '", ` ~ actual ~ `, "'");` `assert(false);}`; } used as: mixin(assertEqual("foo","bar")); If you can live with a) having to use 'mixin', b) ugliness of compile time string manipulation and perhaps c) sometimes hard to follow error messages, you can do most of anything you want with CTFE and string mixins. I think if one would make work of this most of the tediousness could be solved with some boilerplate code.
Aug 17 2007
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Also note that it is necessary to 'public import std.metastrings' if 
this code is used across modules, due to the mixin thing.
Aug 17 2007
prev sibling parent reply Bruce Adams <tortoise_74 yada.yahoo.yada.nospamme.co.uk> writes:
Lutger Wrote:

 Bruce Adams wrote:
 
 Here are a few more things I've learned on my travels around the various D
web-pages.
 
 __FILE__ & __LINE__ are expanded by the tokeniser not the parser. This implies
that they would not be available for use in mixins as they will already have
been expanded. This is confirmed with a quick test. So what I'm trying to do is
not currently possible.
It's possible to use CTFE with string mixins to achieve this. I have whipped up something quick, ugly as hell but could be improved using std.metastrings.Format: char[] assertEqual(char[] actual, char[] expected) { return `if (` ~ actual ~ `!=` ~ expected ~ `) { ` `writefln("Equality assertion failed in " ~ __FILE__ ~ " at line " ~ std.metastrings.ToString!(__LINE__));` `writefln("expected value: '", ` ~ expected ~ `, "'");` `writefln("actual value: '", ` ~ actual ~ `, "'");` `assert(false);}`; } used as: mixin(assertEqual("foo","bar")); If you can live with a) having to use 'mixin', b) ugliness of compile time string manipulation and perhaps c) sometimes hard to follow error messages, you can do most of anything you want with CTFE and string mixins. I think if one would make work of this most of the tediousness could be solved with some boilerplate code.
I'd rather live with A) - than without the option to do this at all. B) is better than it was in C++. I'm already struggling with C) using DMD, if you'll pardon the pun. I can see from using a variant of your example that is possible now. I forgot we had CTFE. I was surprised it allows arbitrary strings to be compiled as I though mxins were supposed to use code segments that have been parsed already. Anyway, I'm still struggling a bit with it. My main problem can be boiled down to the following example. char[] int2str(int foo_) { return std.metastrings.ToString!(foo_); } Fails to compile with c:\dmd\bin\..\src\phobos\std\metastrings.d(102): Error: expression cast(long)foo _ is not a valid template value argument c:\dmd\bin\..\src\phobos\std\metastrings.d(85): Error: expression cast(long)foo_ < 0L is not constant or does not evaluate to a bool Without the shriek it also fails: char[] int2str(int foo_) { return std.metastrings.ToString(foo_); } dmd.exe -c UnitTest.d -ofUnitTest.do -cov c:\dmd\bin\..\src\phobos\std\metastrings.d(74): template std.metastrings.ToStrin g(ulong U) is not a function template UnitTest.d(124): template std.metastrings.ToString(ulong U) cannot deduce templa te function from argument types (int) UnitTest.d(124): Error: cannot implicitly convert expression ((ToString(ulong U) )(foo_)) of type int to char[] Its not obvious to me what I'm doing wrong. Incidentally is there a way of specifying you only want a function to be evaluated at compile time? Perhaps the static keyword? My plan when this kind of thing comes up is to have one function for the run-time portion and a seperate code generator for the compile time stuff. Regards, Bruce.
Aug 19 2007
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Bruce Adams wrote:
...
 I can see from using a variant of your example that is possible now.
 I forgot we had CTFE. I was surprised it allows arbitrary strings to be
compiled as I though mxins were supposed to use code segments that have been
parsed already.
 Anyway, I'm still struggling a bit with it. My main problem can be boiled
 down to the following example.
 
 char[] int2str(int foo_)
 {
    return std.metastrings.ToString!(foo_);
 }
This is almost correct, see below.
 char[] int2str(int foo_)
 {
    return std.metastrings.ToString(foo_);
 }
std.metastrings.ToString is a template, which must be instanciated with !, so this is not correct. My example was bad, I'm sorry, it didn't break because I only used these __LINE__ and __FILE__ tokens. At the very bottom of http://www.digitalmars.com/d/function.html the reason is explained: "Any functions that execute at compile time must also be executable at run time. The compile time evaluation of a function does the equivalent of running the function at run time. " For int2str, this is not the case. If you only need compile time execution, you can rewrite these functions as templates. For my original example: template assertEqual(char[] actual, char[] expected) { const char[] assertEqual = `if (` ~ actual ~ `!=` ~ expected ~ `) { ` `writefln("Equality assertion failed in " ~ __FILE__ ~ " at line " ~ std.metastrings.ToString!(__LINE__));` `writefln("expected value: '", ` ~ expected ~ `, "'");` `writefln("actual value: '", ` ~ actual ~ `, "'");` `assert(false);}`; } mixin(assertEqual!("foo","bar"));
 Incidentally is there a way of specifying you only want a function to be
evaluated at compile time? Perhaps the static keyword?
 My plan when this kind of thing comes up is to have one function for
 the run-time portion and a seperate code generator for the compile time stuff.
See the eval template also at http://www.digitalmars.com/d/function.html To determine whether a parameter is a constant or not (for dispatching), perhaps one could use is-expressions to try to take the adress: is( typeof(&arg)). That should evaluate to false for constants (at compile time), but true for run-time parameters. Haven't tested it though.
Aug 20 2007
parent reply Bruce Adams <tortoise_74 yahoo.no.spamno.menot.co.uk> writes:
Right, thanks. I'm nearly there. 
Here's where I'm at:

// for example only
void assertWrapper(char[] file_, uint line_) {
      _d_assert(file_,line_);
}
 
// the run-time assert part
void assertEqual(Type)(Type actual_, Type expected_, 
		       char[] file_, 
		       uint line_) {
   if (actual_ != expected_) {
      writefln("Equality assertion failed");
      writefln("actual:   '", actual_, "'");
      writefln("expected: '", expected_, "'");
   }
   assertWrapper(file_,line_);
}

const char[] assertEqual4(const char[] actualVar_, const char[] expectedVar_) {
   return "assertEqual!(int)("[]
      ~actualVar_
      ~","[]
      ~expectedVar_
      ~",cast(char[])(__FILE__),__LINE__);"[]; 
}

const char[] assertEqual5(T)(const char[] actualVar_, const char[]
expectedVar_) {
   return "assertEqual!(" 
      ~typeof(T).stringof
      ~")("[]
      ~actualVar_
      ~","[]
      ~expectedVar_
      ~",cast(char[])(__FILE__),__LINE__);"[]; 
}

unittest {
   // declare at run-time
   const int var3 = 1;
   const int var4 = 2;

   int var5 = 1;
   int var6 = 2;

    // okay - but must give name of variables
   writefln(assertEqual4("var5"[],"var6"[]));
   mixin(assertEqual4("var5"[],"var6"[]));

   // must provide name and type
   mixin(assertEqual5!(int)("var5"[],"var6"[]));

   // must provide name and type
   mixin(assertEqual5!(typeof(var5))(var5.stringof,var6.stringof));
}

I reckon "mixin(assertEqual(var5,var6));" should be possible but I haven't
quite figured it out yet.

Regards,

Bruce.


Lutger Wrote:

[Some helpful stuff]
Aug 20 2007
parent reply Bruce Adams <tortoise_74 no.spam.anywhere.anytime.yahoo.uk> writes:
Hi all,
       Still stuck. How do I get the template to include the name of a run-time
variable at compile-time? Please somebody put me out of my misery.

template assertEqual8(actual_, expected_)
{
   const char[] assertEqual8(actual_ a_, expected_ e_) { 
      return 
	 "mixin(assertEqual5!("[]
	 ~actual_.stringof
	 ~")("[]
	 ~a_.stringof
	 ~","[]
	 ~e_.stringof
	 ~"));"[];
   }
}
alias assertEqual8!(int, int) assertEqual9;

unittest {
   // all fine
   // writes: "mixin(assertEqual5!(int)(a_,e_));" when var5, var6 wanted
   writefln(assertEqual9(var5,var6));

   // not allowed at CT :(
   mixin(assertEqual9(var5,var6))
}

UnitTest.d(246): Error: variable var5 is used before initialization
UnitTest.d(246): Error: cannot evaluate assertEqual8(var5,var6) at compile time
UnitTest.d(246): Error: argument to mixin must be a string, not (assertEqual8(va
r5,var6))


Bruce Adams Wrote:

 
 Right, thanks. I'm nearly there. 
 Here's where I'm at:
 
 // for example only
 void assertWrapper(char[] file_, uint line_) {
       _d_assert(file_,line_);
 }
  
 // the run-time assert part
 void assertEqual(Type)(Type actual_, Type expected_, 
 		       char[] file_, 
 		       uint line_) {
    if (actual_ != expected_) {
       writefln("Equality assertion failed");
       writefln("actual:   '", actual_, "'");
       writefln("expected: '", expected_, "'");
    }
    assertWrapper(file_,line_);
 }
 
 const char[] assertEqual4(const char[] actualVar_, const char[] expectedVar_) {
    return "assertEqual!(int)("[]
       ~actualVar_
       ~","[]
       ~expectedVar_
       ~",cast(char[])(__FILE__),__LINE__);"[]; 
 }
 
 const char[] assertEqual5(T)(const char[] actualVar_, const char[]
expectedVar_) {
    return "assertEqual!(" 
       ~typeof(T).stringof
       ~")("[]
       ~actualVar_
       ~","[]
       ~expectedVar_
       ~",cast(char[])(__FILE__),__LINE__);"[]; 
 }
 
 unittest {
    // declare at run-time
    const int var3 = 1;
    const int var4 = 2;
 
    int var5 = 1;
    int var6 = 2;
 
     // okay - but must give name of variables
    writefln(assertEqual4("var5"[],"var6"[]));
    mixin(assertEqual4("var5"[],"var6"[]));
 
    // must provide name and type
    mixin(assertEqual5!(int)("var5"[],"var6"[]));
 
    // must provide name and type
    mixin(assertEqual5!(typeof(var5))(var5.stringof,var6.stringof));
 }
 
 I reckon "mixin(assertEqual(var5,var6));" should be possible but I haven't
quite figured it out yet.
 
 Regards,
 
 Bruce.
 
 
 Lutger Wrote:
 
 [Some helpful stuff]
 
Aug 21 2007
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Bruce Adams wrote:
 Hi all,
        Still stuck. How do I get the template to include the name of a
run-time variable at compile-time? Please somebody put me out of my misery.
 
 template assertEqual8(actual_, expected_)
 {
    const char[] assertEqual8(actual_ a_, expected_ e_) { 
       return 
 	 "mixin(assertEqual5!("[]
 	 ~actual_.stringof
 	 ~")("[]
 	 ~a_.stringof
 	 ~","[]
 	 ~e_.stringof
 	 ~"));"[];
    }
 }
 alias assertEqual8!(int, int) assertEqual9;
 
 unittest {
    // all fine
    // writes: "mixin(assertEqual5!(int)(a_,e_));" when var5, var6 wanted
    writefln(assertEqual9(var5,var6));
 
    // not allowed at CT :(
    mixin(assertEqual9(var5,var6))
 }
 
 UnitTest.d(246): Error: variable var5 is used before initialization
 UnitTest.d(246): Error: cannot evaluate assertEqual8(var5,var6) at compile time
 UnitTest.d(246): Error: argument to mixin must be a string, not
(assertEqual8(va
 r5,var6))
 
 
 Bruce Adams Wrote:
 
 Right, thanks. I'm nearly there. 
 Here's where I'm at:

 // for example only
 void assertWrapper(char[] file_, uint line_) {
       _d_assert(file_,line_);
 }
  
 // the run-time assert part
 void assertEqual(Type)(Type actual_, Type expected_, 
 		       char[] file_, 
 		       uint line_) {
    if (actual_ != expected_) {
       writefln("Equality assertion failed");
       writefln("actual:   '", actual_, "'");
       writefln("expected: '", expected_, "'");
    }
    assertWrapper(file_,line_);
 }

 const char[] assertEqual4(const char[] actualVar_, const char[] expectedVar_) {
    return "assertEqual!(int)("[]
       ~actualVar_
       ~","[]
       ~expectedVar_
       ~",cast(char[])(__FILE__),__LINE__);"[]; 
 }

 const char[] assertEqual5(T)(const char[] actualVar_, const char[]
expectedVar_) {
    return "assertEqual!(" 
       ~typeof(T).stringof
       ~")("[]
       ~actualVar_
       ~","[]
       ~expectedVar_
       ~",cast(char[])(__FILE__),__LINE__);"[]; 
 }

 unittest {
    // declare at run-time
    const int var3 = 1;
    const int var4 = 2;

    int var5 = 1;
    int var6 = 2;

     // okay - but must give name of variables
    writefln(assertEqual4("var5"[],"var6"[]));
    mixin(assertEqual4("var5"[],"var6"[]));

    // must provide name and type
    mixin(assertEqual5!(int)("var5"[],"var6"[]));

    // must provide name and type
    mixin(assertEqual5!(typeof(var5))(var5.stringof,var6.stringof));
 }

 I reckon "mixin(assertEqual(var5,var6));" should be possible but I haven't
quite figured it out yet.

 Regards,

 Bruce.


 Lutger Wrote:

 [Some helpful stuff]
Try this... void assertEqual (T) (T actual, T expected, char[] file, uint line) { if (actual != expected) { writeln("Equality assertion failed."); writefln(" actual: '%s'", actual); writefln(" expected: '%s'", expected); _d_assert(file, line); } } template MAssertEqual (alias actual, alias expected) { const MAssertEqual = `assertEqual(` ~actual.stringof~ `, ` ~expected.stringof~ `, __FILE__, __LINE__);` ; } unittest { int var5 = 1; int var6 = 2; mixin(MAssertEqual!(var5, var6)); // -> assertEqual(var5, var6, __FILE__, __LINE__); } Note: Untested. -- Chris Nicholson-Sauls
Aug 22 2007
parent Bruce Adams <whycantthis stupidreaderrememberme.com> writes:
Chris Nicholson-Sauls Wrote:
 
 Try this...
 
 void assertEqual (T) (T actual, T expected, char[] file, uint line) {
    if (actual != expected) {
      writeln("Equality assertion failed.");
      writefln("  actual:   '%s'", actual);
      writefln("  expected: '%s'", expected);
      _d_assert(file, line);
    }
 }
 
 template MAssertEqual (alias actual, alias expected) {
    const MAssertEqual =
      `assertEqual(`
      ~actual.stringof~
      `, `
      ~expected.stringof~
      `, __FILE__, __LINE__);`
    ;
 }
 
 unittest {
    int var5 = 1;
    int var6 = 2;
 
    mixin(MAssertEqual!(var5, var6)); // -> assertEqual(var5, var6, __FILE__,
__LINE__);
 }
 
 Note: Untested.
 
 -- Chris Nicholson-Sauls
That doesn't work, but this does: template MAssertEqual (alias actual, alias expected) { const AssertEqual = `assertEqual!(` ~typeof(actual).stringof ~`)(` ~actual.stringof~ `, ` ~expected.stringof~ `, cast(char[])(__FILE__), __LINE__);` ; } So problem solved. I'm not sure why template type deduction isn't working here (a D2.0 issue?), but thanks anyway. I can now run away and write Dunit if someone hasn't already done it. Of course, if they had and I knew about it I probably wouldn't have started this thread. Thanks, I've learned a bit more useful template meta foo. Regards, Bruce
Aug 24 2007
prev sibling parent reply Bruce Adams <ifyoudontknowmebynow searchdaweb.com> writes:
Okay. So having realised my first idea is not possible with current D (prove me
wrong please!). What about the char array versus string
malarcky. Can anyone help with that?

How do I get "foo" to be implicitly interpreted as char[] rather than
char[3]. I though the WYSIWYG thing might do it i.e. r"foo" but it
doesn't. In fact I'm not sure what it does do.

Bruce Adams Wrote:

 
 Hi,
     Another FAQ item I couldn't find. I'm looking to implement some wrappers
around assert as assert is too primative and doesn't give me enough
information. I want to go down the xUnit path E.g.
 
 in the code:
    assertEqual(foo,bar);
 
 leading to output:
    Equality assertion failed in file.cpp at line 10
    Expected Value: 10
    Actual Value: 5
 
 I got as far as:
 
 void assertEqual(Type)(Type actual_, 
                                 Type expected_, 
 		            char[] file_, 
 		            uint line_) {
    if (actual_ != expected_) {
       writefln("Equality assertion failed");
       writefln("actual:   '", actual_, "'");
       writefln("expected: '", expected_, "'");
       _d_assert(file_,line_);
    }
 }
 
 This lets me use:
 
    assertEqual!(string)("foo","bar",cast(char[])(__FILE__),__LINE__);
 
 Where I'm having trouble is getting __FILE__ and __LINE__ added (presumably
using a mixin) so I can avoid the cruft.
 
 As a side issue how do I get string constants implicitly converted to
 char[] or better yet string.
 In my example above
 
    assertEqual("foo","bar",cast(char[])(__FILE__),__LINE__);
 
 also works but only because "foo".length == "bar".length
 
    // broken!
    assertEqual("foo","bar2",cast(char[])(__FILE__),__LINE__);
 
 Final question to prove I'm a noob. In std.asserterror shouldn't 
 
  _d_assert(char[] file_,uint line_);
 
 actually be:
 
  _d_assert(string file_,uint line_);
 
 Regards,
 
 Bruce.
 
Aug 16 2007
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
Bruce Adams schrieb:
 How do I get "foo" to be implicitly interpreted as char[] rather than
 char[3]. 
"foo"[]
Aug 16 2007
parent reply Bruce Adams <ifyoudontknowmebynow searchdaweb.com> writes:
Frank Benoit Wrote:

 Bruce Adams schrieb:
 How do I get "foo" to be implicitly interpreted as char[] rather than
 char[3]. 
"foo"[]
Thanks. Where is that piece of syntactic sugar documented? There's still a problem though. The following line: assertEqual("foo"[],"bar2"[],cast(char[])(__FILE__),__LINE__); fails to compile with: UnitTest.d(49): template UnitTest.assertEqual(Type) cannot deduce template fun ion from argument types (invariant(char)[],invariant(char)[],char[],long) but the explicit instantiation below works. assertEqual!(invariant(char[]))("foo"[],"bar2"[],cast(char[])(__FILE__),__LINE__); What's going on? Regards, Bruce.
Aug 16 2007
parent Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Bruce Adams wrote:
 Frank Benoit Wrote:
 Bruce Adams schrieb:
 How do I get "foo" to be implicitly interpreted as char[] rather than
 char[3]. 
"foo"[]
Thanks. Where is that piece of syntactic sugar documented?
http://www.digitalmars.com/d/arrays.html "The [] is shorthand for a slice of the entire array." -- Remove ".doesnotlike.spam" from the mail address.
Aug 17 2007