www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Get calling this, if exists

reply "Smoke" Adams <SA2432 gmail.com> writes:
Is there a type of __THIS__ construct similar to __FILE__ and 
__LINE__?

Something that returns the current this ptr if it exists, null 
otherwise.

Log(string filename = __FILE__, Object obj = __THIS__)()
{
    // inspect obj and do stuff
}
Jun 23 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 24 June 2016 at 02:57:28 UTC, "Smoke" Adams wrote:
 Is there a type of __THIS__ construct similar to __FILE__ and 
 __LINE__?

 Something that returns the current this ptr if it exists, null 
 otherwise.

 Log(string filename = __FILE__, Object obj = __THIS__)()
 {
    // inspect obj and do stuff
 }
There is no 'this' pointer unless you are calling a member function on an aggregate, so you can never have one that is null.
Jun 23 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 24 June 2016 at 03:04:25 UTC, Mike Parker wrote:
 On Friday, 24 June 2016 at 02:57:28 UTC, "Smoke" Adams wrote:
 Is there a type of __THIS__ construct similar to __FILE__ and 
 __LINE__?

 Something that returns the current this ptr if it exists, null 
 otherwise.

 Log(string filename = __FILE__, Object obj = __THIS__)()
 {
    // inspect obj and do stuff
 }
There is no 'this' pointer unless you are calling a member function on an aggregate, so you can never have one that is null.
Oh, perhaps I misunderstood your question. Do you meant this: class Foo() { void bar() { Log(); } // Pass reference to Foo instance } void doSomething() { Log(); } // Null reference If so, the answer is no. And I don't see how that could work as a compile time parameter, given that the reference itself is a runtime value.
Jun 23 2016
parent reply Meta <jared771 gmail.com> writes:
On Friday, 24 June 2016 at 03:10:51 UTC, Mike Parker wrote:
 Oh, perhaps I misunderstood your question. Do you meant this:

 class Foo() {
    void bar() { Log(); }  // Pass reference to Foo instance
 }

 void doSomething() { Log(); } // Null reference

 If so, the answer is no. And I don't see how that could work as 
 a compile time parameter, given that the reference itself is a 
 runtime value.
It actually is possible. You just have to be explicit. void log(alias self)(string s) { pragma(msg, self.stringof); } struct Test { void test(string s) { log!this(s); } } void main() { Test t; t.test("asdf"); }
Jun 23 2016
parent reply "Smoke" Adams <SA2432 gmail.com> writes:
On Friday, 24 June 2016 at 03:16:58 UTC, Meta wrote:
 On Friday, 24 June 2016 at 03:10:51 UTC, Mike Parker wrote:
 Oh, perhaps I misunderstood your question. Do you meant this:

 class Foo() {
    void bar() { Log(); }  // Pass reference to Foo instance
 }

 void doSomething() { Log(); } // Null reference

 If so, the answer is no. And I don't see how that could work 
 as a compile time parameter, given that the reference itself 
 is a runtime value.
It actually is possible. You just have to be explicit. void log(alias self)(string s) { pragma(msg, self.stringof); } struct Test { void test(string s) { log!this(s); } } void main() { Test t; t.test("asdf"); }
I don't want to be explicit! One can be explicit with __FILE__ too but one doesn't have to be. I don't care if it's null.
Jun 24 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/24/16 11:15 AM, Smoke Adams wrote:
 On Friday, 24 June 2016 at 03:16:58 UTC, Meta wrote:
 On Friday, 24 June 2016 at 03:10:51 UTC, Mike Parker wrote:
 Oh, perhaps I misunderstood your question. Do you meant this:

 class Foo() {
    void bar() { Log(); }  // Pass reference to Foo instance
 }

 void doSomething() { Log(); } // Null reference

 If so, the answer is no. And I don't see how that could work as a
 compile time parameter, given that the reference itself is a runtime
 value.
It actually is possible. You just have to be explicit. void log(alias self)(string s) { pragma(msg, self.stringof); } struct Test { void test(string s) { log!this(s); } } void main() { Test t; t.test("asdf"); }
I don't want to be explicit! One can be explicit with __FILE__ too but one doesn't have to be.
__FILE__ is a constant, so is __LINE__. __THIS__ would not be, so this is somewhat different. With UFCS, you can get close: void log(T)(T obj, string s) { ... } struct Test { void test(string s) { this.log(s); } } But I believe you have to call with explict 'this'. Perhaps an opDispatch can help, but seems an awful lot to avoid explicit passing of this variable. -Steve
Jun 24 2016
parent reply "Smoke" Adams <SA2432 gmail.com> writes:
On Friday, 24 June 2016 at 15:35:57 UTC, Steven Schveighoffer 
wrote:
 On 6/24/16 11:15 AM, Smoke Adams wrote:
 On Friday, 24 June 2016 at 03:16:58 UTC, Meta wrote:
 On Friday, 24 June 2016 at 03:10:51 UTC, Mike Parker wrote:
 Oh, perhaps I misunderstood your question. Do you meant this:

 class Foo() {
    void bar() { Log(); }  // Pass reference to Foo instance
 }

 void doSomething() { Log(); } // Null reference

 If so, the answer is no. And I don't see how that could work 
 as a
 compile time parameter, given that the reference itself is a 
 runtime
 value.
It actually is possible. You just have to be explicit. void log(alias self)(string s) { pragma(msg, self.stringof); } struct Test { void test(string s) { log!this(s); } } void main() { Test t; t.test("asdf"); }
I don't want to be explicit! One can be explicit with __FILE__ too but one doesn't have to be.
__FILE__ is a constant, so is __LINE__. __THIS__ would not be, so this is somewhat different. With UFCS, you can get close: void log(T)(T obj, string s) { ... } struct Test { void test(string s) { this.log(s); } } But I believe you have to call with explict 'this'. Perhaps an opDispatch can help, but seems an awful lot to avoid explicit passing of this variable. -Steve
The problem with UFCS is that I am using variadic parameters. The logging function isn't designed to accept the first parameter as this. It would be much easier to simply have the compiler "insert" it using __THIS__. Just because it isn't constant isn't really that big of a deal to the compiler. It could just manually add the parameter at the end of of the arguments. I would also have to convert all the calls to this.log. This becomes problematic because not not all calls are inside objects. We have __FUNCTION__ so, __THIS__ seems somewhat natural. Null for outside of objects is fine.
Jun 24 2016
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/24/16 1:19 PM, Smoke Adams wrote:
 The problem with UFCS is that I am using variadic parameters. The
 logging function isn't designed to accept the first parameter as this.
Then you would need to change it?
 It would be much easier to simply have the compiler "insert" it using
 __THIS__. Just because it isn't constant isn't really that big of a deal
 to the compiler. It could just manually add the parameter at the end of
 of the arguments.
Yes, easier for you not having to do anything. It's only the compiler writers who have to figure out how to add this feature for you :)
 I would also have to convert all the calls to this.log.

 This becomes problematic because not not all calls are inside objects.
Possibly you can use overloads. In any case, I think there is some work you need to do to get what you want.
 We have __FUNCTION__ so, __THIS__ seems somewhat natural. Null for
 outside of objects is fine.
__FUNCTION__ is still a compile-time constant. Have you considered a mixin or opDispatch to help you out? (untested) mixin template addLog() { log(this This, T...)(T args) { return .log(cast(This)this, args); } } class MyBaseObj { mixin addLog; } class MyObj : MyBaseObj { void foo() { log(1, 2, 3); // calls .log(cast(MyObj)this, 1, 2, 3) } } -Steve
Jun 24 2016
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/24/2016 10:19 AM, Smoke Adams wrote:

 We have __FUNCTION__ so, __THIS__ seems somewhat natural. Null for
 outside of objects is fine.
Would the following work, where you check the first argument? import std.stdio; void Log(string filename = __FILE__, T...)(T args) { static if (is (T[0] == typeof(null))) { writefln("working without an object for %s", args[1 .. $]); } else static if (is (T[0] == class)) { writefln("working with object %s and %s", args[0], args[1 .. $]); } else { // Recurse import std.meta : AliasSeq; return Log!filename(AliasSeq!(null, args)); } } class C { } void main() { Log(42, "hello"); auto c = new C(); Log(c, "cool"); c.Log("breeze"); } The output: working without an object for 42 working with object deneme.C and cool working with object deneme.C and breeze Ali
Jun 24 2016