<div dir="ltr"><div>Maybe someone has a pattern for doing this kind of thing...</div><div><br></div><div>So, I have a function that does something to a various set of things; let's say we're going to serialise them or something:</div><div><br></div><div>```<br></div><div>module serialise;</div><div><br></div><div>void serialise(T)(void[] buffer, T)</div><div>  if (isSomeInt!T)</div><div>{ /* serialise integer */ }</div><div><br></div><div>
<div>void serialise(void[] buffer, const(char)[] str)</div><div>{ /* serialise string */ }</div><div><br></div><div>// ...etc</div><div>```</div><div><br></div><div>And some serialiser somewhere calls `serialise(thing)` for each thing, where the type of thing chooses the right overload and we're all good... sure, everyone knows this pattern.</div><div><br></div><div>So, I add a user thing in a module somewhere:</div><div><br></div><div>```<br></div><div>module app.user_thing:</div><div><br></div><div>struct UserThing</div><div>{ ... }</div><div><br></div><div>void serialise(void[] buffer, ref UserThing t)</div><div>{ /* serialise UserThing */ }</div><div>```</div><div><br></div><div>Now this thing wants to be serialisable, so you implement a serialise function beside it...</div><div>In C++, this works; because ADL (argument dependent lookup) will cause to additionally search the scope where the argument is defined for overloads. Trouble is, in D unless `app.user_thing` was imported inside the serialiser where it makes the call to `serialise()`, this overload won't be found, because the UserThing overload is not in scope for the serialiser.</div><div><br></div><div>I tried to simulate something like ADL by getting `__traits(parent, value)` in a loop until I find the module for non-builtin objects, and then have the serialiser import that module prior to the call, to attempt to make sure the argument's module is also in scope so any potential overloads can be found when it tries to make the call:</div><div><br></div><div>import default_serialise : serialise;<br></div><div><br></div><div>void doSerialise(Things...)(void[] buffer, Things things)</div><div></div><div>{</div><div>  static foreach (thing; things)</div><div>  {{</div><div>    static if (isUserType!thing)</div><div>    {</div><div>      enum thingMod = getModuleForThing!thing;</div><div>      mixin(import " ~ 
thingMod

 ~ ";");<br></div><div>    }</div><div>    serialise(buffer thing);<br></div><div>  }}<br></div><div>}<br></div><div><br></div><div>The surprise is that if `thingMod` has a symbol `serialise`, it imports it at the inner scope, and it shadows the global overload set rather than complementing it...</div><div><br></div><div>So, I guess the thing I'm stuck on is; given there are some imports at global scope, and it may have an overload set for some function; HOW can I import more items to that overload set?</div><div><br></div><div>I tried this, but it doesn't work:</div><div><br></div><div>
<div>import default_serialise : serialise;<br></div><div><br></div><div>void doSerialise(Things...)(void[] buffer, Things things)</div><div></div><div>{</div><div>  static foreach (thing; things)</div><div>  {{</div><div>    static if (isUserType!thing)</div><div>    {</div><div>      enum thingMod = getModuleForThing!thing;</div><div>      mixin(import " ~ 
thingMod

 ~ ";");<br></div><div>
<div>      import default_serialise : serialise; // re-import at inner scope, beside the other one<br></div>

    }</div><div>    serialise(buffer thing);<br></div><div>  }}<br></div><div>}<br></div><div><br></div><div>Re-importing the globals into the same scope doesn't cause them to combine either; just the symbol from whichever import statement appears first is the winner...</div><div><br></div><div>Has anyone ever experimented with a pattern like this? Essentially, I can't work out how to expand /combine an overload set to include symbols from multiple imports....<br></div>

</div>

</div></div>