Как использовать front () в константном массиве - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть эта функция, extract(), которая принимает диапазон и имя члена, затем пытается создать диапазон переноса, чей front() обеспечивает доступ только к названному члену.

Проблемалежит в Range.front(), когда R имеет форму const(T)[].Компилятор указывает, что функция r.front() не существует.Я вполне уверен, что что-то не так с взаимодействием между non-const R и const r.front(), но я не уверен, как его решить.

Итак, правильна ли моя интуиция?И в любом случае, что именно не так, и как я могу это исправить?

auto extract (string member, R)(R range) {
    import std.traits: hasMember;
    import std.range: ElementType, isInputRange;

    static assert(hasMember!(ElementType!R, member));
    static assert(isInputRange!R);

    struct Range {
        R r;
        bool empty ()() { return r.empty; }
        void popFront ()() { r.popFront; }
        ElementType!R front () { mixin("return r.front." ~ member ~ ";"); }
    }

    return Range(range);
}

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Во-первых.Если вы хотите сохранить свою реализацию, вам следует заменить

import std.range: ElementType, isInputRange;

на

import std.range: ElementType, isInputRange, front;

и

ElementType!R front () { mixin("return r.front." ~ member ~ ";"); }

на

auto front () { mixin("return r.front." ~ member ~ ";"); }

Но.Ваша реализация слишком сложна

Это может быть более упрощенным.

Просто

auto extract1 (string member, R)(R range)
    if((hasMember!(ElementType!R, member)) && isInputRange!R)
{
    return range.map!("a." ~ member);
}
0 голосов
/ 13 февраля 2019

Оказывается, вам нужно std.range.primitives.front(), если вы собираетесь работать с массивом, и поскольку имена связываются настолько близко, насколько это возможно, нет конфликта имен (если R реализует front(), его вызывают вместоодин из std.range).

Однако, по причинам, которые я не понимаю, вы не можете выборочно импортировать его.Вы должны импортировать все std.range.primitives.

. В любом случае, учитывая структуру S:

struct S {
    string name;
}

и массив:

const(S)[] a = [S("A"), S("B")];

Вызовtest.extract!"name"() правильно возвращает ["A", "B"].

...