On Fri, Feb 02, 2018 at 07:06:56AM +0000, Simen Kjærås via Digitalmars-d-learn 
> Which code would you rather write?
> void foo(T)(const T t) {}
> foo(myValue);
> or:
> void foo(T)(T t) if (isTailConst!T) {}
> foo(myValue.tailConst);

More thoughts on this: what if we made it so that Wrapper!T is
implicitly convertible to Wrapper!(const T)? Something like this:

        auto foo(Wrapper,T)(Wrapper!(const(T)) t) ...

        struct Wrapper(T) {
                auto tailConst() {
                        return Wrapper!(const(T))(...);
                alias tailConst this;

        void main() {
                Wrapper!int w;

It will interact badly if Wrapper is already using alias this for
something else, but this lets us keep the convenience of implicitly
decaying to tail-const without requiring an explicit call to .tailConst.

Though the above currently doesn't compile, it seems because the
compiler doesn't know how to resolve Wrapper!(const(T)) given a
Wrapper!T despite the alias this. However, removing `Wrapper` from the
template arguments of foo() does work; and seems to have the right
semantics.  Seems to be just a limitation of IFTI.  So calling a
function that expects, say, RefCounted!(const T), with an argument of
type RefCounted!T can already be made to work today, if we tie
.tailConst to alias this.

The fully general solution will have to wait until we can improve IFTI
to support the generic case where the wrapper type is also a template
parameter.  Might be worth filing an enhancement against the compiler to
support this?

If this can be made to work, we may not even need a standard name for
.tailConst, as long as the wrapper type can somehow make itself decay
into its tail-const version implicitly.


In theory, there is no difference between theory and practice.

Reply via email to