ADL

vit via Digitalmars-d digitalmars-d at puremagic.com
Sat Sep 3 10:00:24 PDT 2016


On Saturday, 3 September 2016 at 13:04:30 UTC, Andrei 
Alexandrescu wrote:
> On 9/3/16 1:24 PM, Walter Bright wrote:
>> On 9/3/2016 3:12 AM, Walter Bright wrote:
>>> If you are still determined to use it, you can use:
>>>
>>>    __traits(compiles, ...)
>>>
>>> like you would SFINAE in C++ to select which of the modules 
>>> from the
>>> argument
>>> types selects a function that compiles.
>>
>> Eh, I realized it's simpler than that. Based on the code I 
>> already
>> presented, each argument can be used to generate an import for 
>> its
>> corresponding version of the function. Then, overloading rules 
>> apply and
>> it works. Something like:
>>
>> Something like:
>>
>> void foo(T,U)(T t, U u)
>> {
>>     alias func = ModuleOf!T.func;
>>     alias func = ModuleOf!U.func;
>>
>>     func(t, u);
>> }
>
> This only works with the respective modules do define `func`. 
> We need something that conditionally plants the symbol 
> depending on whether the module defines it or not. -- Andrei


perhaps this:

auto adl(string fn, T, Args...)(auto ref T x, auto ref Args args){
     import std.traits : moduleName, hasMember;
     import std.meta : Filter, NoDuplicates, staticMap;
     import std.array : join;

     static if(hasMember!(T, fn)){
         mixin("return x." ~ fn ~ "(args);");
     }
     else{
         enum toImportString(T) = "import " ~ moduleName!(T) ~ " : 
" ~ fn ~ ";";
         enum hasModuleFN(T) = __traits(compiles, mixin("(){" ~ 
toImportString!T ~ "}"));
         alias Types = Filter!(hasModuleFN, NoDuplicates!(T, 
Args));

         static assert(Types.length, "no property '" ~ fn ~ "' for 
type '" ~ __traits(identifier, T)~ "'");

         mixin([staticMap!(toImportString, Types),"return " ~ fn ~ 
"(x, args);"].join("\n"));
     }
}



More information about the Digitalmars-d mailing list