Можно ли автоматически реализовать признак для любого кортежа, состоящего из типов, которые все реализуют признак? - PullRequest
0 голосов
/ 06 апреля 2019

Предположим, что у меня есть

trait Happy {}

Я могу реализовать Happy для любой структуры, которую я могу захотеть, например:

struct Dog;
struct Cat;
struct Alligator;

impl Happy for Dog {}
impl Happy for Cat {}
impl Happy for Alligator {}

Теперь я хотел бы автоматически *Черта 1008 * my Happy для любого кортежа состоит из типов, которые все реализуют черту Happy.Интуитивно, кортеж всех счастливых тоже счастлив.

Возможно ли сделать такое?Например, я могу тривиально расширить реализацию Happy на любой кортеж из двух Happy типов:

impl <T, Q> Happy for (T, Q) where T: Happy, Q: Happy {}

В результате это прекрасно компилируется:

fn f(_: impl Happy) {
}

fn main() {
    f((Dog{}, Alligator{}));
}

Нокак я могу обобщить это на любой кортеж любой длины?Насколько я понимаю, у нас нет универсальных переменных в Rust.Есть ли обходной путь?

1 Ответ

5 голосов
/ 07 апреля 2019

У нас нет универсальных переменных в Rust.

Правильно.

Есть ли обходной путь?

Вы используете макрос:

trait Happy {}

macro_rules! tuple_impls {
    ( $head:ident, $( $tail:ident, )* ) => {
        impl<$head, $( $tail ),*> Happy for ($head, $( $tail ),*)
        where
            $head: Happy,
            $( $tail: Happy ),*
        {
            // interesting delegation here, as needed
        }

        tuple_impls!($( $tail, )*);
    };

    () => {};
}

tuple_impls!(A, B, C, D, E, F, G, H, I, J,);

Теперь он компилируется:

fn example<T: Happy>() {}

fn call<A: Happy, B: Happy>() {
    example::<(A, B)>();
} 

Обычно это не считается большой проблемой, поскольку длинные кортежи в основном не читаются, и вы всегда можете вкладывать кортежи, еслидействительно необходимо.

См. также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...