Thread overview | |||||
---|---|---|---|---|---|
|
October 27, 2019 Supporting inout haystack in array-overload of findSplitBefore without template-bloat | ||||
---|---|---|---|---|
| ||||
Is it possible to make this array-overload of findSplitBefore support `inout`-qualified `haystack` parameter and return type without using a templated `Result`? auto findSplitBefore(T)(scope const T[] haystack, // TODO support inout? scope const T needle) { struct Result { private alias Haystack = typeof(haystack); private Haystack _haystack; private size_t _offset; inout(Haystack) pre() inout @trusted { return _haystack.ptr[0 .. _offset]; } inout(Haystack) post() inout @trusted { if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[_offset .. _haystack.length]; } bool opCast(T : bool)() const { return !_isMiss; } private bool _isMiss() const { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return Result(haystack, offset); } } return Result(haystack, haystack.length); } /// @safe pure nothrow @nogc unittest { const r = "a*b".findSplitBefore('*'); assert(r); assert(r.pre == "a"); assert(r.post == "*b"); } This is my attempt so far auto findSplitAfter(T)(scope inout(T)[] haystack, // TODO support inout? scope const T needle) @trusted { struct Result { private T[] _haystack; private size_t _offset; inout(T)[] pre() inout @trusted { if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } inout(T)[] post() inout @trusted { if (_isMiss) { return _haystack[0 .. $]; } return _haystack.ptr[_offset + 1 .. _haystack.length]; } bool opCast(T : bool)() const @trusted { return !_isMiss; } private bool _isMiss() const @trusted { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return inout(Result)(haystack, offset); } } return inout(Result)(haystack, haystack.length); } /// @safe pure nothrow @nogc unittest { const r = "a*b".findSplitAfter('*'); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); } which results in the following interesting compiler error: array_algorithm.d(506,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function assert(r.pre == "a*"); ^ array_algorithm.d(507,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function assert(r.post == "b"); ^ array_algorithm.d(514,5): Error: static assert: `is(typeof(r.pre()) == const(char)[])` is false static assert(is(typeof(r.pre()) == const(char)[])); |
October 27, 2019 Re: Supporting inout haystack in array-overload of findSplitBefore without template-bloat | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On Sunday, 27 October 2019 at 14:29:01 UTC, Per Nordlöw wrote: > which results in the following interesting compiler error: > > > array_algorithm.d(506,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function > assert(r.pre == "a*"); > ^ > array_algorithm.d(507,12): Error: modify `inout` to `immutable` is not allowed inside `inout` function > assert(r.post == "b"); > ^ > array_algorithm.d(514,5): Error: static assert: `is(typeof(r.pre()) == const(char)[])` is false > static assert(is(typeof(r.pre()) == const(char)[])); A non-templated and less bloated but still suboptimal solution is to defined inlined overloads for the member functions, this case `pre()`: auto findSplitAfter_inout(T)(scope inout(T)[] haystack, scope const T needle) @trusted { static struct Result { private T[] _haystack; private size_t _offset; auto pre() @trusted { pragma(inline, true); if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } auto pre() const @trusted { pragma(inline, true); if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } auto pre() immutable @trusted { pragma(inline, true); if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } auto post() const @trusted { if (_isMiss) { return _haystack[0 .. $]; } return _haystack.ptr[_offset + 1 .. _haystack.length]; } bool opCast(T : bool)() const { return !_isMiss; } private bool _isMiss() const { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return inout(Result)(haystack, offset); } } return inout(Result)(haystack, haystack.length); } /// @safe pure nothrow @nogc unittest { auto r = "a*b".findSplitAfter_inout('*'); static assert(is(typeof(r.pre()) == string)); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); } |
October 27, 2019 Re: Supporting inout haystack in array-overload of findSplitBefore without template-bloat | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On Sunday, 27 October 2019 at 14:57:29 UTC, Per Nordlöw wrote: > @safe pure nothrow @nogc unittest > { > auto r = "a*b".findSplitAfter_inout('*'); > static assert(is(typeof(r.pre()) == string)); > assert(r); > assert(r.pre == "a*"); > assert(r.post == "b"); > } Made it work! :) /** Array-overload for `findSplitAfter` with default predicate. * * See_Also: https://forum.dlang.org/post/dhxwgtaubzbmjaqjmnmq@forum.dlang.org */ auto findSplitAfter(T)(scope inout(T)[] haystack, // TODO support inout? See_Also: https://forum.dlang.org/post/jtpchtddgenhjuwhqdsq@forum.dlang.org scope const T needle) @trusted { static struct Result { private T[] _haystack; private size_t _offset; pragma(inline, true): inout(T)[] pre() @trusted inout { if (_isMiss) { return _haystack[$ .. $]; } return _haystack.ptr[0 .. _offset + 1]; } inout(T)[] post() @trusted inout { if (_isMiss) { return _haystack[0 .. $]; } return _haystack.ptr[_offset + 1 .. _haystack.length]; } bool opCast(T : bool)() const { return !_isMiss; } private bool _isMiss() const { return _haystack.length == _offset; } } foreach (const offset, const ref e; haystack) { if (e == needle) { return inout(Result)(haystack, offset); } } return inout(Result)(haystack, haystack.length); } /// @safe pure nothrow @nogc unittest { char[] haystack; auto r = haystack.findSplitAfter('*'); static assert(is(typeof(r.pre()) == char[])); static assert(is(typeof(r.post()) == char[])); } /// @safe pure nothrow @nogc unittest { const(char)[] haystack; auto r = haystack.findSplitAfter('*'); static assert(is(typeof(r.pre()) == const(char)[])); static assert(is(typeof(r.post()) == const(char)[])); } /// @safe pure nothrow @nogc unittest { auto r = "a*b".findSplitAfter('*'); static assert(is(typeof(r.pre()) == string)); static assert(is(typeof(r.post()) == string)); assert(r); assert(r.pre == "a*"); assert(r.post == "b"); } |
Copyright © 1999-2021 by the D Language Foundation