On Sunday, 23 December 2018 at 18:31:24 UTC, Alex wrote:
On Sunday, 23 December 2018 at 18:13:25 UTC, Vijay Nayar wrote:
For example, if you have a const function in your container like "T find() const", and this function needs to use that comparator, then you're out of luck because the compiler doesn't know that the comparator function is const and will not modify the objects being compared.

Last time I ran into this problem, my solution was simply to give up on const. But now I'm running into it again and trying to think through it again before giving up again.

Hm... still not sure... ;)
This would compile and run:

´´´
import std.experimental.all;

size_t myHashFunction(int a) { return cast(size_t) a; }

void main()
{
        auto b = new B!(int, myHashFunction);
        b.arr = 42.iota.array;
        assert(b.find == 1);
}

class B(T, alias HashF)
{
        T[] arr;

        T find() const
        {
                foreach(el; arr)
                {
                        if(HashF(el))
                        {
                                return el;
                        }
                }
                assert(0);
        }
}
´´´

You're right, it does compile. I'm a bit surprised. I wonder if this is a relatively recent improvement in the language, because last time I ran into this I had no such luck. But after seeing that your example did work, I figured one could try to get the best of both worlds by using a strongly-typed wrapper function in one's class. So far it seems to work:

import std.traits;

class A(KeyT, alias HashF) {
// Strongly-typed wrapper around template value parameter 'HashF'.
  static size_t hash(in KeyT key) {
    return HashF(key);
  }
  static this() {
static assert(isCallable!HashF, "Hash function is not callable!"); static assert(Parameters!(HashF).length == 1, "Hash function must take 1 argument.");
    static assert(is(Parameters!(HashF)[0] : const(KeyT)),
        "Hash parameter must be const.");
    static assert(is(typeof(HashF(KeyT.init)) : size_t),
        "Hash function must return size_t type.");
  }

  KeyT data;
  size_t getHash() const {
    return hash(data);
  }
}

void main() {
    auto a = new A!(int, (int a) => cast(size_t) a);
    a.data = 5;
    a.getHash();
}

Reply via email to