История изменений
Исправление 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"))