Как я могу сопоставить кортеж с кортежем, содержащим перечисление & amp; mut, и использовать перечисление в руке соответствия?

Просто добавьте что-то примечательное здесь.


myQueue.hpp:

template <class T> 
class QueueA {
    int size;
    ...
public:
    template <class T> T dequeue() {
       // implementation here
    }

    bool isEmpty();

    ...
}    

myQueue можно определить методы шаблонного класса, которые просто прекрасны в файле реализации. cpp:

// implementation of regular methods goes like this:
template <class T> bool QueueA<T>::isEmpty() {
    return this->size == 0;
}


main()
{
    QueueA<char> Q;

    ...
}
0
задан Ákos Vandra 13 July 2018 в 17:22
поделиться

1 ответ

Нет, это небезопасно. Вы пытаетесь ввести изменяемое сглаживание внутри рукава матча. Измененная ссылка a указывает на то же значение, что и self. Можно было бы изменить self (например, *self = Foo::Foo1(99)), который затем аннулирует a, поэтому этот код не разрешен.

Вместо этого mutably reborrow self в выражении match и вернуть ему первое значение кортежа. Так как это значение не имеет ссылки на self, вы можете вернуть self с результатом match:

enum Foo {
    Foo1(u32),
    Foo2(u32), // changed so I don't have to figure out what casting you meant
}

impl Foo {
   fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
        let next = match (&mut *self, y) {
            (Foo::Foo1(a), b @ 5) => {
                *a = b + 42;
                b
            }

            (Foo::Foo2(a), b @ 5) => {
                *a = b + 42;
                *a * b
            }

            _ => y,
        };

        (next, self)
    }
}

Однако возврат self, как это, скорее здесь бессмысленно. У вызывающего уже есть &mut Foo, поэтому вам не нужно «возвращать его». Это позволяет упростить:

impl Foo {
    fn bar(&mut self, y: u32) -> u32 {
         match (self, y) {
            (Foo::Foo1(a), b @ 5) => {
                *a = b + 42;
                b
            }

            (Foo::Foo2(a), b @ 5) => {
                *a = b + 42;
                *a * b
            }

            _ => y,
        }
    }
}

Я бы сказал, что это безопасная операция, хотя компилятор, возможно, не сможет понять, что

С неэлексические времена жизни , средство проверки займов становится более интеллектуальным. Ваш исходный код с добавленным явным компилятором reborrow:

#![feature(nll)]

enum Foo {
    Foo1(u32),
    Foo2(u32), // changed so I don't have to figure out what casting you meant
}

impl Foo {
   fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
        match (&mut *self, y) {
            (Foo::Foo1(a), b @ 5) => {
                *a = b + 42;
                (b, self)
            }

            (Foo::Foo2(a), b @ 5) => {
                *a = b + 42;
                (*a * b, self)
            }

            _ => (y, self),
        }
    }
}

См. Также:

2
ответ дан Shepmaster 17 August 2018 в 12:23
поделиться
  • 1
    Спасибо за ввод - хотя псевдоним происходит только во время возврата, поэтому я бы сказал, что это безопасная операция, хотя компилятор, возможно, не сможет это понять. Однако ваш ответ также указывает на то, что мой пример слишком сильно ошарашен. В реальном сценарии структура данных является самореференцией, и я фактически возвращаю поддерево исходного кода, я настрою свой вопрос, чтобы лучше отразить это – Ákos Vandra 13 July 2018 в 17:15
  • 2
    @ ÁkosVandra редактирование таких вопросов, что они аннулируют существующие ответы, как правило, неодобрительно. – Shepmaster 13 July 2018 в 17:20
  • 3
    Извините, вернул изменения и отправил новый вопрос: stackoverflow.com/questions/51330147/… – Ákos Vandra 13 July 2018 в 17:28
  • 4
    @ ÁkosVandra и мое редактирование о NLL не происходит, чтобы решить вашу проблему? – Shepmaster 13 July 2018 в 17:29
Другие вопросы по тегам:

Похожие вопросы: