www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Easy way to accept X and immutable X in parameters without

reply Jack <jckj33 gmail.com> writes:
let's say a I have this:

void f(X foo) { }

but I'd like to make f() accept immutable X too so instead of 
cast away everywhere in the code where immutable(X) is passed to 
f() or make a overload for this, are there any way to accept both 
in same function? those function are callback-like functions, I 
have lots of them so already and would need to double, if I do 
add an overload just for the immutable. I did come up with 
something using templates, not sure if it's ugly:

void f(T)(T x)
if(is(T == C) || is(T == immutable(C)) {
// ...
}
Jan 11 2021
parent reply ag0aep6g <anonymous example.com> writes:
On Monday, 11 January 2021 at 16:40:01 UTC, Jack wrote:
 let's say a I have this:

 void f(X foo) { }

 but I'd like to make f() accept immutable X too so instead of 
 cast away everywhere in the code where immutable(X) is passed 
 to f() or make a overload for this, are there any way to accept 
 both in same function? those function are callback-like 
 functions, I have lots of them so already and would need to 
 double, if I do add an overload just for the immutable. I did 
 come up with something using templates, not sure if it's ugly:

 void f(T)(T x)
 if(is(T == C) || is(T == immutable(C)) {
 // ...
 }
Accepting both mutable and immutable is what `const` is for: void f(const X foo) { ... }
Jan 11 2021
parent reply Jack <jckj33 gmail.com> writes:
On Monday, 11 January 2021 at 16:56:05 UTC, ag0aep6g wrote:
 On Monday, 11 January 2021 at 16:40:01 UTC, Jack wrote:
 let's say a I have this:

 void f(X foo) { }

 but I'd like to make f() accept immutable X too so instead of 
 cast away everywhere in the code where immutable(X) is passed 
 to f() or make a overload for this, are there any way to 
 accept both in same function? those function are callback-like 
 functions, I have lots of them so already and would need to 
 double, if I do add an overload just for the immutable. I did 
 come up with something using templates, not sure if it's ugly:

 void f(T)(T x)
 if(is(T == C) || is(T == immutable(C)) {
 // ...
 }
Accepting both mutable and immutable is what `const` is for: void f(const X foo) { ... }
thanks! now, how would I add const here? import std.container : SList; auto l = SList!Callabck(); doesn't work: auto l = SList!(const(Callabck())); auto l = SList!(const Callabck());
Jan 11 2021
parent reply ag0aep6g <anonymous example.com> writes:
On Monday, 11 January 2021 at 18:12:17 UTC, Jack wrote:
 thanks! now, how would I add const here?

 import std.container : SList;
 auto l = SList!Callabck();

 doesn't work:

 auto l = SList!(const(Callabck()));
 auto l = SList!(const Callabck());
You said you want the callbacks to accept both mutable and immutable. So make the parameter `const` in the callback type: alias Callabck = void function(const X foo); If you wanted an `SList` of `const Callabck`s, you'd write that like so: auto l = SList!(const Callabck)(); But it seems like `SList` doesn't support const elements. And I don't think that's what you actually want anyways. (By the way, you've got a typo there in "Callabck".)
Jan 11 2021
parent reply Jack <jckj33 gmail.com> writes:
On Monday, 11 January 2021 at 18:37:58 UTC, ag0aep6g wrote:
 On Monday, 11 January 2021 at 18:12:17 UTC, Jack wrote:
 thanks! now, how would I add const here?

 import std.container : SList;
 auto l = SList!Callabck();

 doesn't work:

 auto l = SList!(const(Callabck()));
 auto l = SList!(const Callabck());
You said you want the callbacks to accept both mutable and immutable. So make the parameter `const` in the callback type: alias Callabck = void function(const X foo);
I did exactly that and SList template initilization failed
 If you wanted an `SList` of `const Callabck`s, you'd write that 
 like so:

     auto l = SList!(const Callabck)();

 But it seems like `SList` doesn't support const elements. And I 
 don't think that's what you actually want anyways.
What I want is store a instance of Callback, whose parameter accept both immutable and non-immutable (so I used const) in the SList but it failed to initialize
 (By the way, you've got a typo there in "Callabck".)
oh i see but I did write this code just for this post anyway. Here's what I'm trying to make to work: import std.container : SList; class C { static immutable Foo = new C(); // .... } alias Callback = void function(const C, int); void main() { auto l = SList!Callback(); auto a = (C c, int d) { }; auto b = (C c, int d) { }; auto c = (const C c, int d) { }; l.insert(a); l.insert(b); l.insert(c); }
Jan 11 2021
next sibling parent ag0aep6g <anonymous example.com> writes:
On Monday, 11 January 2021 at 18:51:04 UTC, Jack wrote:
 Here's what I'm trying to make to work:

 import std.container : SList;

 class C
 {
     static immutable Foo = new C();
    // ....
 }

 alias Callback = void function(const C, int);

 void main()
 {
     auto l = SList!Callback();
     auto a = (C c, int d) { };
     auto b = (C c, int d) { };
     auto c = (const C c, int d) { };
     l.insert(a);
     l.insert(b);
     l.insert(c);
 }
I'm assuming that you then want to call the callbacks on mutable and immutable `C`s like `C.Foo`. You have to add `const` to the `a` and `b` functions, too: auto a = (const C c, int d) { }; auto b = (const C c, int d) { }; Without those `const`s, you have callbacks with mutable parameters being called on an immutable object. That cannot work.
Jan 11 2021
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Monday, 11 January 2021 at 18:51:04 UTC, Jack wrote:
 alias Callback = void function(const C, int);

 void main()
 {
     auto l = SList!Callback();
     auto a = (C c, int d) { };
     auto b = (C c, int d) { };
     auto c = (const C c, int d) { };
     l.insert(a);
     l.insert(b);
     l.insert(c);
 }
You have a type mismatch. Changing the code to use explicit type annotations instead of `auto` makes the problem obvious: alias Callback = void function(const C, int); void main() { Callback a = (C c, int d) { }; // Error Callback b = (C c, int d) { }; // Error Callback c = (const C c, int d) { }; } The error message given is the same for both lines: Error: cannot implicitly convert expression `__lambda1` of type `void function(C c, int d) pure nothrow nogc safe` to `void function(const(C), int)` In other words, `a` and `b` are not valid Callbacks, because they take a mutable C argument instead of a const C argument.
Jan 11 2021