Разнообразна шаблонна функция с аргументи от един и същи тип

Как да огранича шаблонна функция с различни варианти, така че всички нейни аргументи да бъдат от един и същи тип?

Имам нужда от това за специализация на

CommonType!T either(T...)(T a) if (a.length >= 1)
{
    static if (T.length == 1)
        return a[0];
    else
        return a[0] ? a[0] : either(a[1 .. $]);
}

който може да препраща l-стойности, използвайки auto ref като тип връщане. Нещо по пътя

auto ref either(T...

това трябва да задоволи

unittest {
    int x = 1, y = 2;
    either(x, y) = 3;
    assert(x == 3);
}

Това позволява стойностите да бъдат препращани през логическите either и every (не са показани) подобно на and() и or() на Lisps.

Това би позволило още по-мощно използване на функционални конструкции в D за тези, които го предпочитат.

Актуализация

Вярвам, че намерих работещо решение като:

/** Returns: true if all types T are the same. */
template allSame(T...) {
    static if (T.length <= 1) {
        enum bool allSame = true;
    } else {
        enum bool allSame = is(T[0] == T[1]) && allSame!(T[1..$]);
    }
}

CommonType!T either(T...)(T a) if (a.length >= 1) {
    static if (T.length == 1) {
        return a[0];
    } else {
        return a[0] ? a[0] : either(a[1 .. $]);
    }
}
auto ref either(T...)(ref T a) if (a.length >= 1 && allSame!T) {
    static if (T.length == 1) {
        return a[0];
    } else {
        return a[0] ? a[0] : either(a[1 .. $]);
    }
}

alias either or;

Въпреки това тялото на двете версии на either е идентично. Това изглежда ненужно. Mixin най-добрият начин ли е да се премахне това излишък?


person Nordlöw    schedule 07.09.2013    source източник


Отговори (2)


Ще трябва да напишете шаблон, който определя дали всички типове в кортеж от типове са еднакви:

template allSame(T...)
{
    static if (T.length <= 1)
        enum bool allSame = true;
    else
        enum bool allSame = is(T[0] == T[1]) && allSame!(T[1..$]);
} 

След това просто използвайте това като ограничение на шаблона:

CommonType!T either(T...)(T a) if (a.length >= 1 && allSame!T)
person Peter Alexander    schedule 07.09.2013
comment
И аз бях изненадан. Фобос има доста функции за кортежи от типове, но няма тази. - person Peter Alexander; 07.09.2013
comment
Моето решение работи в повечето случаи. Въпреки това, ако искаме да препраща и препратки към const и immutable, смятам, че трябва да модифицирам по някакъв начин втория пример. Но не знам как да посоча променливия аргумент ref T a като inout. Някакви идеи? - person Nordlöw; 12.09.2013

По отношение на вашия шаблон allSame можете също да използвате allSatisfy от std.typetuple:

import std.typetuple;

/** Returns: true if all types T are the same. */
template allSame(T...) {

    template isType(X) { enum bool isType = is(X == T[0]); }
    enum bool allSame = allSatisfy!(isType, T);
}

void main()
{
    static assert(!allSame!(int, float, string));
    static assert(allSame!(int, int, int));
    static assert(allSame!(int));
}
person Andrej Mitrović    schedule 07.09.2013
comment
Също така може да направи (NoDuplicates!T).length == 1, въпреки че не е толкова самодокументиращ се :) - person Peter Alexander; 07.09.2013
comment
Това е хубаво! Още 3 знака (не ме карайте да започвам с правилата на SO..) - person Andrej Mitrović; 07.09.2013