www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - caller trouble

reply captaindet <2krnk gmx.net> writes:
i need a discreet handle on the calling/instantiating source file (module).
using __FILE__, it is surprisingly easy for functions (via argument) and
templated functions (via template parameter) but i cannot get it working for
templated classes. how can i make them aware of the calling module?

thx, det


module other;

string fun(string infile = __FILE__){ return infile; }
string tfun(string infile = __FILE__)(){ return infile; }
class tclass(string infile = __FILE__){ string from = infile; }

//...//

module main;	
import other;

void main(){
     auto _fun = fun();			//_fun == "main.d"
     auto _tfun = tfun();		//_tfun == "main.d"
     auto _tclass = new tclass!();	//_tclass.from == "other.d" !!!

     //this works but i do not want to provide __FILE__ explicitly:
     auto _tclassx = new tclass!(__FILE__)();	//_tclass.from == "main.d"
     //and why do i get 2 different results for the last 2 cases?
}
Jul 13 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, July 14, 2012 01:53:34 captaindet wrote:
 i need a discreet handle on the calling/instantiating source file (module).
 using __FILE__, it is surprisingly easy for functions (via argument) and
 templated functions (via template parameter) but i cannot get it working
 for templated classes. how can i make them aware of the calling module?
 
 thx, det
 
 
 module other;
 
 string fun(string infile = __FILE__){ return infile; }
 string tfun(string infile = __FILE__)(){ return infile; }
 class tclass(string infile = __FILE__){ string from = infile; }
 
 //...//
 
 module main;
 import other;
 
 void main(){
      auto _fun = fun();			//_fun == "main.d"
      auto _tfun = tfun();		//_tfun == "main.d"
      auto _tclass = new tclass!();	//_tclass.from == "other.d" !!!
 
      //this works but i do not want to provide __FILE__ explicitly:
      auto _tclassx = new tclass!(__FILE__)();	//_tclass.from == "main.d"
      //and why do i get 2 different results for the last 2 cases?
 }

I believe that __FILE__ and __LINE__ are treated specially with functions in order for them to be filled in at the call site rather than the declaration site. If it's not working with classes, then that probably means that whatever special logic was done to make them work with functions was only done for functions. If you want, you can open an enhancement request: http://d.puremagic.com/issues However, I would point out that that would mean that every single module which uses tclass would end up with a different and incompatible instantiations of tclass, so if __FILE__ worked with class templates like you want it to, then any such class wouldn't work outside of the module that it was constructed in save for code that uses auto and typeof to get the type. And I have hard time believing that that would be a good idea. With a templated function, it doesn't really matter if two different call points end up with different instantiations. They'll both work just fine. But having a class which only works in the module where it's instantiated would be _far_ more limiting. However, if you _really_ want something like this, you can always just wrap the creation of the object in a function: auto create(string infile = __FILE__, Args...)(Args args) { return new tclass!infile(args); } Args isn't necessary if there are no arguments for the constructor, but it _is_ if there are, and it'll work if there aren't. - Jonathan M Davis
Jul 14 2012
parent captaindet <2krnk gmx.net> writes:
On 2012-07-14 02:12, Jonathan M Davis wrote:
[..]
 I believe that __FILE__ and __LINE__ are treated specially with
 functions in order for them to be filled in at the call site rather
 than the declaration site. If it's not working with classes, then
 that probably means that whatever special logic was done to make them
 work with functions was only done for functions.

IIRC, __FILE__ is a template itself. so it must be about the very moment it is resolved. apparently, for function (templates) default parameters are treated as if given on the caller side. maybe even for __FILE__ and __LINE__ as main usage case? in any case, there would be a consistent rule "resolve all templates in argument lists on caller side, including default parameters" if it were not broken for class templates. moreover, i am puzzled why the small variation in usage rusults in an inconsistent outcome: auto _tclass = new tclass!(); //_tclass.from == "other.d" !!! auto _tclassx = new tclass!(__FILE__)(); //_tclass.from == "main.d"
 However, I would point out that that would mean that every single
 module which uses tclass would end up with a different and
 incompatible instantiations of tclass

yes, but not an issue in my case. there would be only one object, created from the main module. background: i want to do some compile time magic including parsing information from a file that always has the same name as the module containing main(){...}.
 However, if you _really_ want something like this, you can always
 just wrap the creation of the object in a function:

good idea, i will try this next. thanks for your help! /det
Jul 14 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, July 14, 2012 13:30:03 captaindet wrote:
 IIRC, __FILE__ is a template itself

It's not. It's a special symbol recognized by the compiler, and ends up in several places in the grammar. - Jonathan M Davis
Jul 14 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/14/2012 08:53 AM, captaindet wrote:
 i need a discreet handle on the calling/instantiating source file
 (module). using __FILE__, it is surprisingly easy for functions (via
 argument) and templated functions (via template parameter) but i cannot
 get it working for templated classes. how can i make them aware of the
 calling module?

 thx, det


 module other;

 string fun(string infile = __FILE__){ return infile; }
 string tfun(string infile = __FILE__)(){ return infile; }
 class tclass(string infile = __FILE__){ string from = infile; }

 //...//

 module main;
 import other;

 void main(){
      auto _fun = fun();            //_fun == "main.d"
      auto _tfun = tfun();        //_tfun == "main.d"
      auto _tclass = new tclass!();    //_tclass.from == "other.d" !!!

      //this works but i do not want to provide __FILE__ explicitly:
      auto _tclassx = new tclass!(__FILE__)();    //_tclass.from == "main.d"
      //and why do i get 2 different results for the last 2 cases?
 }

This is a bug. dlang.org agrees: http://dlang.org/template.html#TemplateValueParameter
Jul 14 2012
parent captaindet <2krnk gmx.net> writes:
 auto _fun = fun(); //_fun == "main.d"
 auto _tfun = tfun(); //_tfun == "main.d"
 auto _tclass = new tclass!(); //_tclass.from == "other.d" !!!

 //this works but i do not want to provide __FILE__ explicitly:
 auto _tclassx = new tclass!(__FILE__)(); //_tclass.from == "main.d"
 //and why do i get 2 different results for the last 2 cases?
 }

This is a bug. dlang.org agrees: http://dlang.org/template.html#TemplateValueParameter

right, i missed this in the specs. there seem to be several bug reports on this and related issues, eg: http://d.puremagic.com/issues/show_bug.cgi?id=4018 http://d.puremagic.com/issues/show_bug.cgi?id=5686 apparently and old issue that was never addressed...too bad
Jul 14 2012