LINUX.ORG.RU

История изменений

Исправление red75prim, (текущая версия) :

fallible конструктор в nothrow контексте

Вам ехать или шашечки?

Да, давно плюсы не вспоминал. Смешал noexcept и -fno-exceptions. Компиляция С++ в режиме без поддержки исключений сейчас, наверно, исключение?

В Расте этот минус (а его уже было бы достаточно) осложняется еще больше. Так, эта функция не может быть перегружена.

Это просто попытка использовать подходы C++ в расте, который предлагает другие средства для решения таких задач. Перегрузка (то есть ad-hoc полиморфизм) - это в данном случае сахар для работы с разными функциями, названными одним именем. Да, придётся назвать разные функции по разному.

Более того, я не могу вызвать функцию для произвольного T

Вообще-то можно. Нужно только назвать вещи своими именами: конструктор с параметрами - это замыкание, которое возвращает Result<T, E>.

noexcept конструктор, соответственно возвращает Result<T, !> (! - это never или bottom тип)

fn foo<T, E, F>(create: F) -> Result<(), E>
where
    F: FnOnce() -> Result<T, E>
{
    let a = create()?;
    // или
    let mut ts = vec![];
    ts.push(create()?);
    Ok(())
}

Реализуется через замыкания: Foo::with(|| Bar { .. }).

Не реализуется. Владение безусловно передается в замыкание.

Реализуется. Перемещать или нет аргументы конструктора в замыкание решает тот, кто пишет замыкание.

|| Bar::new(&a) - а не перемещается

move || Bar::new(a) - перемещается

|| Bar::new(a.clone()) - клонируется

Перемещается, если конструктор был вызван:

let mut a = Some(a);
|| Bar::new(a.take().expect("bug"))

Исправление red75prim, :

fallible конструктор в nothrow контексте

Вам ехать или шашечки?

Да, давно плюсы не вспоминал. Смешал noexcept и -fno-exceptions. Компиляция С++ в режиме без поддержки исключений сейчас, наверно, исключение?

В Расте этот минус (а его уже было бы достаточно) осложняется еще больше. Так, эта функция не может быть перегружена.

Это просто попытка использовать подходы C++ в расте, который предлагает другие средства для решения таких задач. Перегрузка (то есть ad-hoc полиморфизм) - это в данном случае сахар для работы с разными функциями, названными одним именем. Да, придётся назвать разные функции по разному.

Более того, я не могу вызвать функцию для произвольного T

Вообще-то можно. Нужно только назвать вещи своими именами: конструктор с параметрами - это замыкание, которое возвращает Result<T, E>.

noexcept конструктор, соответственно возвращает Result<T, !> (! - это never или bottom тип)

fn foo<T, E, F>(create: F) -> Result<(), E>
where
    F: FnOnce() -> Result<T, E>
{
    let a = create();
    // или
    let mut ts = vec![];
    ts.push(create()?);
    Ok(())
}

Реализуется через замыкания: Foo::with(|| Bar { .. }).

Не реализуется. Владение безусловно передается в замыкание.

Реализуется. Перемещать или нет аргументы конструктора в замыкание решает тот, кто пишет замыкание.

|| Bar::new(&a) - а не перемещается

move || Bar::new(a) - перемещается

|| Bar::new(a.clone()) - клонируется

Перемещается, если конструктор был вызван:

let mut a = Some(a);
|| Bar::new(a.take().expect("bug"))

Исходная версия red75prim, :

fallible конструктор в nothrow контексте

Вам ехать или шашечки?

Да, давно плюсы не вспоминал. Смешал noexcept и -fno-exceptions. Компиляция С++ в режиме без поддержки исключений сейчас, наверно, исключение?

В Расте этот минус (а его уже было бы достаточно) осложняется еще больше. Так, эта функция не может быть перегружена.

Это просто попытка использовать подходы C++ в расте, который предлагает другие средства для решения таких задач. Перегрузка (то есть ad-hoc полиморфизм) - это в данном случае сахар для работы с разными функциями, названными одним именем. Да, придётся назвать разные функции по разному.

Более того, я не могу вызвать функцию для произвольного T

Вообще-то можно. Нужно только назвать вещи своими именами: конструктор с параметрами - это замыкание, которое возвращает Result<T, E>.

noexcept конструктор, соответственно возвращает Result<T, !> (! - это never или bottom тип)

fn foo<T, E, F>(constructor: F) -> Result<(), E>
where
    F: FnOnce() -> Result<T, E>
{
    let a = constructor();
    // или
    let mut ts = vec![];
    ts.push(constructor()?);
    Ok(())
}

Реализуется через замыкания: Foo::with(|| Bar { .. }).

Не реализуется. Владение безусловно передается в замыкание.

Реализуется. Перемещать или нет аргументы конструктора в замыкание решает тот, кто пишет замыкание.

|| Bar::new(&a) - а не перемещается

move || Bar::new(a) - перемещается

|| Bar::new(a.clone()) - клонируется

Перемещается, если конструктор был вызван:

let mut a = Some(a);
|| Bar::new(a.take().expect("bug"))