Re: How to write a counterpart to C++ std::invoke that works with both free functions and methods?
On Tuesday, 29 September 2020 at 01:19:48 UTC, Adam D. Ruppe wrote: On Sunday, 27 September 2020 at 05:22:36 UTC, 60rntogo wrote: How would I check if it is actually a free function? but this doesn't even compile since I defined add inside my main function ah that's not a free function!! OK, I see. That makes sense I suppose. Thanks for putting this together, but I'm afraid that I managed to break it again and this time it is really baffling. --- module foo; auto invoke(alias fun, Args...)(Args args) { static if(__traits(isStaticFunction, fun) || __traits(isNested, fun)) return fun(args); else return __traits(child, args[0], fun)(args[1 .. $]); } unittest { import std : approxEqual; assert(invoke!approxEqual(2.0, 2.001)); } --- This gives me these errors: --- source/foo.d(6,48): Error: aggregate or function expected instead of approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 1e-05) source/foo.d(9,41): Error: template std.math.approxEqual cannot deduce function from argument types !()(double), candidates are: /usr/include/dmd/phobos/std/math.d(8479,6):approxEqual(T, U, V)(T value, U reference, V maxRelDiff = 0.01, V maxAbsDiff = 1e-05) source/foo.d(15,28): Error: template instance foo.invoke!(approxEqual, double, double) error instantiating --- Confusingly, these errors disappear if I include the unit test in my main file (i.e., just add it to the code you posted) rather than foo.d or if I use a function like add defined in the module instead of imported approxEqual. Any ideas?
Re: How to write a counterpart to C++ std::invoke that works with both free functions and methods?
On Saturday, 26 September 2020 at 23:23:13 UTC, Adam D. Ruppe wrote: As a result, you `add` works fine I'm afraid not. __traits(isStaticFunction, add) is false, I think it's because it checks if it is a static member function of some struct/class. How would I check if it is actually a free function? I tried isAggregateType!(__traits(parent, add)) but this doesn't even compile since I defined add inside my main function and __traits(parent, add) evaluates to main, but isAggregateType expects a type as an argument.
Re: conflicting alias in package module
On Sunday, 27 September 2020 at 03:33:20 UTC, Mike Parker wrote: package.d is for your external interface. Fair enough, thanks.
How to write a counterpart to C++ std::invoke that works with both free functions and methods?
I tried this: --- auto invoke(alias fun, Args...)(Args args) { return fun(args); } --- which works with free functions: --- int add(int a, int b) { return a + b; } assert(invoke!add(1, 2) == 3); --- but with a method: --- struct Foo { bool isValid(int a) { return a > 0; } } auto foo = Foo(); assert(invoke!isValid(foo, 3)); --- I get the error "undefined identifier isValid". How can I make this work?
Re: Is it possible to "overload" based on visibility?
On Friday, 25 September 2020 at 18:58:54 UTC, H. S. Teoh wrote: You probably need to use the long-form of templates, with separate function declarations, to accomplish this. E.g.: ... Alright, but your example still contains shouldReturnByRef which presumably I need to implement myself. But that's an optimization detail that I'd rather leave up to the compiler, is that possible?
Re: conflicting alias in package module
On Saturday, 26 September 2020 at 15:12:47 UTC, Steven Schveighoffer wrote: Instead: import pack.foo : Foo; Works. OK, sure. It's just that the motivation behind doing public imports in package.d is that I can write "import pack" instead of "import pack.foo". I guess it simply doesn't work within the package itself.
Re: conflicting alias in package module
On Saturday, 26 September 2020 at 13:45:21 UTC, Steven Schveighoffer wrote: A selective import is equivalent to aliasing (to the public) the symbol as if it were defined in that scope. You have to label it as private if you want it to be private. Are you saying that I should write this in bar.d? private import pack : Foo; This still gives the same error.
conflicting alias in package module
I have a package with the following structure: pack |- foo.d |- bar.d |- package.d and the modules look like this: --- module pack.foo; struct Foo {} --- module pack.bar; import pack : Foo; --- module pack; public import pack.foo, pack.bar; --- and this is an error: "struct pack.foo.Foo at source/pack/foo.d(3,1) conflicts with alias pack.bar.Foo at source/pack/bar.d(3,8)". I seems like the import in package.d sees Foo both in pack.foo and pack.bar, but I don't understand why this happens since the import in bar.d is private, isn't it?
Re: Is it possible to "overload" based on visibility?
On Friday, 25 September 2020 at 15:21:22 UTC, Steven Schveighoffer wrote: If the input is not ref, you should not return by ref, because then you would be returning a reference to local stack data that is about to be destroyed. Yes, I understand that. What I'm really after at this point is that I would like to write a clever mixin that would handle all of these decisions for me. It should generate a function that takes arguments and returns the result by value or const reference depending on what is more appropriate for the given types. I was under the impression that this could be accomplished using in or some other qualifiers.
Re: Is it possible to "overload" based on visibility?
On Friday, 25 September 2020 at 14:21:59 UTC, Steven Schveighoffer wrote: in does not mean "take by reference", it means "scope const" I'm not sure that I really understand scope, but I read https://dlang.org/spec/function.html#param-storage as saying "in means take by value or reference depending on what is better optimized". Is that not what we want here? It depends on if you want to return a copy. If you want to return a reference if the source is a reference, use auto ref on the return as well. But if you still want to protect the internal data, it would have to be const. Right, again I'm wondering if there is a way of saying "just figure out if it's more optimal to return by value or const reference".
Re: Is it possible to "overload" based on visibility?
On Friday, 25 September 2020 at 13:15:27 UTC, Steven Schveighoffer wrote: I don't know, you can search for and report it here: https://issues.dlang.org I find it quite hard to search for anything here, but I couldn't find anything similar so I submitted a bug report. You can use auto ref to alleviate that: int x()(auto ref Foo f) // needs to be a template for auto ref to work That's a good point, thanks. Since we are on that topic, how would that differ from the following? int x(in Foo f) And going further, if instead of int I wanted to return something that might also be expensive to copy, what would be the best way to declare the function?
Re: Is it possible to "overload" based on visibility?
On Wednesday, 23 September 2020 at 19:27:13 UTC, Steven Schveighoffer wrote: This is a bug in the language. Is this a known bug? If not, it should be reported. I came up with an answer to my original question that sort of works: --- module foo; struct Foo { private int x; } int x(Foo f) { return f.x; } --- The downside is that if I don't want to import all of foo at once, then I have to import both Foo and x, but then I can read x from outside the module and modify it form inside as I wanted. Are there any drawbacks of this approach that I'm not seeing?
Re: Is it possible to "overload" based on visibility?
On Wednesday, 23 September 2020 at 19:26:43 UTC, aliak wrote: Yeah, you can make a property setter: private void x(int newValue) { _x = newValue } I'm aware of this, but it does not achieve what I asked for. It only allows me to assign to _x, it doesn't give me a reference to x, so I cannot use it with say += or any other function that takes int by mutable reference.
Is it possible to "overload" based on visibility?
There are really two questions here, one that I intended to ask and one that came out while I was trying to figure out the answer. Consider this simple code: --- module foo; struct Foo { private int _x; int x() const { return _x; } } --- If I have an instance of Foo outside of the module I can read the value of _x using the property method x, but I can only modify it from inside the module using the name _x. This is exactly the kind of encapsulation that I often want, but I'm wondering if this could be improved a little. It would be nice if I didn't have to remember if I need to use _x or x depending on the context. Instead I would like to use only one name, say x, from both inside and outside of the module and have compiler complain if I'm trying to modify it from the outside. My naive attempt was this: --- import std : writeln; private int _x; private ref int x() return { writeln("ref int"); return _x; } int x() const { writeln("int"); return _x; } --- At first I didn't even expect this to compile, but it does and I can call these methods. I believe an overload is chosen based on the type qualifier of a Foo instance. What is truly unexpected is that if I call x on a mutable object even outside of the module, then the first overload is called! So my questions are: 1. Can I achieve my original goal of being able to refer to _x by one name, so that I have read only access from outside the module and read/write access from inside? 2. Is the behavior that allows me to call the private method intended? This is such a blatant violation of encapsulation that it feels like a bug either in the language or the implementation.
Re: another question on hidden mixin names
On Thursday, 17 September 2020 at 22:07:54 UTC, Simen Kjærås wrote: Usually, that would be: struct V { int x; mixin assign!"+" a; mixin assign!"-" b; alias opOpAssign = a.opOpAssign; alias opOpAssign = b.opOpAssign; } However, I can't seem to get that working. It seems to be an instance of this issue: https://issues.dlang.org/show_bug.cgi?id=18118 Yes, I tried that. It didn't work so I assumed that it must have been wrong. Is this a bug in the compiler or an issue in the language specification? btw, I'm somewhat surprised by your use of a template this parameter (https://dlang.org/spec/template.html#template_this_parameter). Generally this will work, but you're probably better off with ref auto opOpAssign(string op)(typeof(this) rhs) if (op == op_) I learned it from here: http://ddili.org/ders/d.en/mixin.html, could you elaborate on why this is not advisable?
another question on hidden mixin names
I suspect that this is similar to the issue I asked about here: https://forum.dlang.org/post/vukxaqprjbyrdpiou...@forum.dlang.org, but I can't figure it out. This compiles: --- private mixin template assign(string op_) { ref auto opOpAssign(string op, this RHS)(RHS rhs) if (op == op_) { mixin("x " ~ op ~ "= rhs.x;"); return this; } } struct V { int x; mixin assign!"+"; // mixin assign!"-"; } unittest { auto v = V(2); v += v; assert(v.x == 4); } --- However, if I uncomment the second mixin, there is an error "v is not a scalar, it is a V". I guess I somehow need to merge these overloads, but I don't know how.
Re: importing a symbol without specifying a subpackage name
On Wednesday, 16 September 2020 at 13:33:34 UTC, Adam D. Ruppe wrote: They define an additional file std/package.d Thanks for a quick answer. I suspected it must have been something like that, except that I tried doing this in foo.d and then the compiler yelled at me.
importing a symbol without specifying a subpackage name
I have noticed that if I want to import std.algorithm.searching.find, each of the following will work: --- import std.algorithm.searching : find; import std.algorithm : find; import std : find; --- (Although, the last one is probably not the greatest idea.) However, if I write my own module: --- module foo.bar; struct Bar {} --- then saying "import foo : Bar;" yields an error "module foo is in file 'foo.d' which cannot be read". I'm curious, how is this behavior achieved in the standard library?
Re: default arguments for const ref parameters in extern C++ functions
On Monday, 14 September 2020 at 17:11:59 UTC, k2aj wrote: AFAIK the only way to have default ref arguments is to use a global variable: --- extern(C++) struct Foo { int x; } immutable foo1 = Foo(1); extern(C++) void fun(const ref Foo foo = foo1); --- Thanks. This appears to work, but feels like a hack. I can live with that, but I'm still wondering if there is a more idiomatic way of solving the problem.
Re: default arguments for const ref parameters in extern C++ functions
On Monday, 14 September 2020 at 12:44:34 UTC, 60rntogo wrote: --- struct Foo { int x; } extern(C++) void fun(const ref Foo foo = Foo(1)); --- I suppose this should have been: --- extern(C++): struct Foo { int x; } void fun(const ref Foo foo = Foo(1)); --- Not that it changes the question in any way.
default arguments for const ref parameters in extern C++ functions
I'm trying to use a C++ library that has a function declared like this: --- struct Foo { int x; }; void fun(const Foo& foo = Foo(1)); --- I have translated this to a D declaration: --- struct Foo { int x; } extern(C++) void fun(const ref Foo foo = Foo(1)); --- This yields an error: "Foo(1) is not an lvalue and cannot be modified". I suppose this makes sense with how D references work, but I have no control over how the C++ function is declared. What can I do with this?
Re: Why does a directly defined constructor hide a mixed-in constructor?
On Sunday, 13 September 2020 at 13:10:15 UTC, Adam D. Ruppe wrote: This is pretty useful in a lot of cases but kinda annoying with overloading. To overload, you must use `alias` to merge the overload sets. For constructors, you need to use the name `__ctor` instead of `this` to make it compile: Yes, that works. Thanks!
Why does a directly defined constructor hide a mixed-in constructor?
This code: --- mixin template X() { int[2] x; this(int[2] x...) { this.x = x; } } struct Foo { } struct Bar { mixin X; this(Foo foo) { this.x = [0, 0]; } } void main() { auto bar = Bar(1, 2); } --- produces the following error: --- source/app.d(27,17): Error: constructor app.Bar.this(Foo foo) is not callable using argument types (int, int) source/app.d(27,17):cannot pass argument 1 of type int to parameter Foo foo --- However, if I directly insert the contents of X into Bar instead of mixing it in, it compiles just fine. What's going on here?
Re: tupleof seems to break encapsulation
On Friday, 4 September 2020 at 17:36:00 UTC, Jacob Carlborg wrote: It's useful for serialization and, as you can see in your example, for debugging as well. `writeln` will print the values of the fields in a struct, even for private fields. I wouldn't dispute that it is useful, but that's besides the point. If I declare something private, it's usually because I want to preserve certain invariants and I want the compiler to provide a guarantee that I don't accidentally violate them. As it stands, the compiler cannot guarantee that if I use tupleof. I don't really have an issue with read-only access to private fields (but arguments could be made against it) and then serialization would still be possible. However, if my struct is supposed to maintain invariants, then any attempt at deserialization that naively reads from a tuple without establishing these invariants should fail to compile.
tupleof seems to break encapsulation
Consider the following code. foo.d --- module foo; struct Foo { private int i; } --- main.d --- void main() { import std.stdio; import foo; auto x = Foo(); writeln(x); // ++x.i; ++x.tupleof[0]; writeln(x); } --- As expected, the commented line does not compile. If I uncomment it, I get the error "no property i for type foo.Foo". However, the rest of the code compiles just fine and outputs: --- Foo(0) Foo(1) --- This appears to defeat the purpose of declaring i private. What am I missing?