Thread overview
problem with custom predicate
May 27, 2015
Simon Bürger
May 27, 2015
drug
May 27, 2015
Simon Bürger
May 27, 2015
Meta
May 27, 2015
Meta
May 27, 2015
Timon Gehr
May 27, 2015
I am trying to use a Container class with a custom predicate, but the following code does not compile. Any hints on how to do it?

import std.container;

class C
{
    int[] prio;
    RedBlackTree!(int, (a,b)=>prio[a]<prio[b]) tree;
}

I think I understand the reason why this does not work (the lambda cannot access the 'this' to get to 'prio'), but I can't think of a way to make it work. Any Ideas?


May 27, 2015
On 27.05.2015 13:50, "Simon Bürger" <simon.buerger@rwth-aachen.de>" wrote:
> I am trying to use a Container class with a custom predicate, but the
> following code does not compile. Any hints on how to do it?
>
> import std.container;
>
> class C
> {
>      int[] prio;
>      RedBlackTree!(int, (a,b)=>prio[a]<prio[b]) tree;
> }
>
> I think I understand the reason why this does not work (the lambda
> cannot access the 'this' to get to 'prio'), but I can't think of a way
> to make it work. Any Ideas?
>
>
Do you want to dynamically change priority? Why prio is outside of your predicate?
May 27, 2015
On Wednesday, 27 May 2015 at 14:58:39 UTC, drug wrote:

> Do you want to dynamically change priority?
Actually yes. In my actual code I am not using a RedBlackTree but my own Container (a heap with the possibility to modify elements inside), which is notified when prio changes so it can do a (local) reordering.

> Why prio is outside of your predicate?
Well, how would I get it into the lambda? In C++ I would use a comparision class, and the constructor of the container would take an instance of that class. But D's RedBlackTree-constructor does not take such a (run-time) argument. And I dont see a way to get prio into the predicate, which is a template-argument.

As I am implementing my own container anyway, I could of course do it the C++-way. But I was wondering if there is another way.
May 27, 2015
On 5/27/15 9:11 AM, "Simon =?UTF-8?B?QsO8cmdlciI=?= <simon.buerger@rwth-aachen.de>" wrote:
> On Wednesday, 27 May 2015 at 14:58:39 UTC, drug wrote:
>
>> Do you want to dynamically change priority?
> Actually yes. In my actual code I am not using a RedBlackTree but my own
> Container (a heap with the possibility to modify elements inside), which
> is notified when prio changes so it can do a (local) reordering.

It would be a very bad idea to change prio if the RBTree is constructed already (and if this works).

>> Why prio is outside of your predicate?
> Well, how would I get it into the lambda? In C++ I would use a
> comparision class, and the constructor of the container would take an
> instance of that class. But D's RedBlackTree-constructor does not take
> such a (run-time) argument. And I dont see a way to get prio into the
> predicate, which is a template-argument.

This is true, RedBlackTree does not take a functor as a parameter to the constructor, it just uses an alias.

This should work if your RedBlackTree is scoped inside a function where the data exists. But at the time of declaration inside the class, the instance of prio doesn't exist, so you can't alias it.

It would be a good enhancement I think to add support for function objects.

-Steve

May 27, 2015
On Wednesday, 27 May 2015 at 15:30:28 UTC, Steven Schveighoffer wrote:
> On 5/27/15 9:11 AM, "Simon =?UTF-8?B?QsO8cmdlciI=?= <simon.buerger@rwth-aachen.de>" wrote:
>> On Wednesday, 27 May 2015 at 14:58:39 UTC, drug wrote:
>>
>>> Do you want to dynamically change priority?
>> Actually yes. In my actual code I am not using a RedBlackTree but my own
>> Container (a heap with the possibility to modify elements inside), which
>> is notified when prio changes so it can do a (local) reordering.
>
> It would be a very bad idea to change prio if the RBTree is constructed already (and if this works).
>
>>> Why prio is outside of your predicate?
>> Well, how would I get it into the lambda? In C++ I would use a
>> comparision class, and the constructor of the container would take an
>> instance of that class. But D's RedBlackTree-constructor does not take
>> such a (run-time) argument. And I dont see a way to get prio into the
>> predicate, which is a template-argument.
>
> This is true, RedBlackTree does not take a functor as a parameter to the constructor, it just uses an alias.
>
> This should work if your RedBlackTree is scoped inside a function where the data exists. But at the time of declaration inside the class, the instance of prio doesn't exist, so you can't alias it.
>
> It would be a good enhancement I think to add support for function objects.
>
> -Steve

I thought unaryFun *does* work with all callables, including structs/classes with opCall?
May 27, 2015
On 05/27/2015 05:30 PM, Steven Schveighoffer wrote:
> On 5/27/15 9:11 AM, "Simon =?UTF-8?B?QsO8cmdlciI=?=
> <simon.buerger@rwth-aachen.de>" wrote:
>> On Wednesday, 27 May 2015 at 14:58:39 UTC, drug wrote:
>>
>>> Do you want to dynamically change priority?
>> Actually yes. In my actual code I am not using a RedBlackTree but my own
>> Container (a heap with the possibility to modify elements inside), which
>> is notified when prio changes so it can do a (local) reordering.
>
> It would be a very bad idea to change prio if the RBTree is constructed
> already (and if this works).
>
>>> Why prio is outside of your predicate?
>> Well, how would I get it into the lambda? In C++ I would use a
>> comparision class, and the constructor of the container would take an
>> instance of that class. But D's RedBlackTree-constructor does not take
>> such a (run-time) argument. And I dont see a way to get prio into the
>> predicate, which is a template-argument.
>
> This is true, RedBlackTree does not take a functor as a parameter to the
> constructor, it just uses an alias.
>
> This should work if your RedBlackTree is scoped inside a function where
> the data exists. But at the time of declaration inside the class, the
> instance of prio doesn't exist, so you can't alias it.
>
> It would be a good enhancement I think to add support for function objects.
>
> -Steve
>

Also, apart from missing implementation, there is no good reason why the code given should not work, is there? I think nested template instantiation should work in all scopes. (Of course, there is the issue that nested structs are somewhat arbitrarily not given a context pointer when declared within a class/struct, so this might be a little inconsistent in case it also works for structs, no question for classes though: just instantiate as nested class.)
May 27, 2015
On 5/27/15 9:59 AM, Meta wrote:
>
> I thought unaryFun *does* work with all callables, including
> structs/classes with opCall?

It (binaryFun actually) declares an alias. But you need an actual instance to use in this case. You simply can't declare that in a type definition, and it won't be set up properly in the constructor even if you could. You need an instance in order to use an alias to that instance.

What likely would happen is if the functor is a callable type, and that type is not a functor itself (i.e. doesn't define static opCall), is that RedBlackTree would then require an instance of that type as part of the constructor.

-Steve
May 27, 2015
On Wednesday, 27 May 2015 at 17:56:27 UTC, Steven Schveighoffer wrote:
> On 5/27/15 9:59 AM, Meta wrote:
>>
>> I thought unaryFun *does* work with all callables, including
>> structs/classes with opCall?
>
> It (binaryFun actually) declares an alias. But you need an actual instance to use in this case. You simply can't declare that in a type definition, and it won't be set up properly in the constructor even if you could. You need an instance in order to use an alias to that instance.
>
> What likely would happen is if the functor is a callable type, and that type is not a functor itself (i.e. doesn't define static opCall), is that RedBlackTree would then require an instance of that type as part of the constructor.
>
> -Steve

Yes, sorry, I meant binaryFun. I remember having a similar problem with tee, and decided to just disallow passing in the name of a struct/class with opCall as a template argument, and instead require that an instance is passed at runtime.