One case of careless opDispatch :)

Robert Jacques sandford at jhu.edu
Thu Jul 15 12:52:56 PDT 2010


On Thu, 15 Jul 2010 15:34:23 -0400, Dmitry Olshansky  
<dmitry.olsh at gmail.com> wrote:

> As a practical habit, once I stumble upon a very tricky error, I usually  
> share the valuable knowledge of "when you do this ... and get that ...  
> it's probably because ... "
> Damn, sometimes they can even become cool quizzes...
> So to warn those oblivious to the dangers of opDispatch, here is my the  
> yesterday nightmare, the striped down code below.
>
> import std.algorithm;
> import std.array;
>
> class Widget {
>      string _name;
>      Widget[] _children;
>      this(in string name){
>          _name = name.idup;
>      }
>      Widget opDispatch(string nm)(){
>          auto r = find!((Widget c){ return c._name == nm; })(_children);
>          return r.front();
>      }
> }
>
> void main(){
>      Widget g = new Widget("G");
>      Widget warr[] = [new Widget("W"),g];
>      find(warr,g);
> }
>
> produces:
>
> Error    1    Error: template std.algorithm.startsWith(alias pred = "a  
> == b",Range,Ranges...) if (isInputRange!(Range) && Ranges.length > 0 &&  
> is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front))))  
> startsWith(alias pred = "a == b",Range,Ranges...) if  
> (isInputRange!(Range) && Ranges.length > 0 &&  
> is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front))))  
> matches more than one template declaration,  
> C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(1892):startsWith(alias  
> pred = "a == b",Range,Ranges...) if (isInputRange!(Range) &&  
> Ranges.length > 0 &&  
> is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0].front))))  
> and  
> C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(1980):startsWith(alias  
> pred = "a == b",Range,Elements...) if (isInputRange!(Range) &&  
> Elements.length > 0 &&  
> is(typeof(binaryFun!(pred)(doesThisStart.front,withOneOfThese[0]))))     
> C:\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d    1488
>
> The tricky part is that *any* class with unconstrained (or loosely  
> constrained) opDispatch is also a Range, and at least a bidirectional  
> one, since it "provides" all the primitives: front, popFront etc.
> In fact such classes could penetrate almost any attempts at C++  
> trait-like stuff  and should be avoided.
>
> The moral: unconstrainted opDispatch == TROUBLE.
> Hope that helps!
>
> P.S. Strangely enough, that problem haven't showed up until update to  
> 2.047 release, so it's probably detonated by some changes to Phobos. I  
> guess better sooner than later.
>

:) I've run into this before, with other compile-time tests such as  
isAssociativeArray. Often, the real bug is the tests themselves are too  
permissive.


More information about the Digitalmars-d mailing list