
fast_float — библиотека для быстрого парсинга чисел с плавающей точкой. Судя по бенчмаркам, быстрее lexical_core, да и вообще практически всех библиотек.
Является портом одноимённой библиотеки для C++ за авторством небезызвестного Даниела Лемира.
Size: a a a
#[test]
-функциях ассертов.#[lang = "copy"]
. Компилятор проверяет, что если тип тем или иным способом задекларирован как Copy
, то и всего его поля должны быть Copy
. Следующий код не компилируется:#[derive(Clone, Copy)]Ошибка:
struct StringHolder(String);
error[E0204]: the trait `Copy` may not be implemented for this type
--> src/lib.rs:1:17
|
1 | #[derive(Clone, Copy)]
| ^^^^
2 | struct StringHolder(String);
| ------ this field does not implement `Copy`
Во-вторых, один и тот же тип не может реализовывать Copy
и Drop
одновременно. Скажем, следующий код не компилируется:#[derive(Clone, Copy)]Ошибка:
struct Primitive;
impl Drop for Primitive {
fn drop(&mut self) {}
}
error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructorТак как полноценных negative trait bounds в Rust всё ещё нет, ограничение
--> src/lib.rs:1:17
|
1 | #[derive(Clone, Copy)]
| ^^^^ Copy not allowed on types with destructors
Copy
можно использовать как более сильную замену ограничению !Drop
.Copy
, "Copies happen implicitly, for example as part of an assignment y = x
. The behavior of Copy
is not overloadable; it is always a simple bit-wise copy.". С другой стороны, Clone
является супертрейтом Copy
, и наличие реализации Copy
не мешает вызывать .clone()
явно. Однако, в отличие от Copy
, Clone::clone
в принципе может вызывать любой код. Поэтому, в частности, технически замена в итераторной цепочке .cloned()
на .copied()
является ломающим изменением, даже если элементы итератора реализуют Copy
.use std::cell::Cell;Если запустить этот код, то он напечатает
struct Counter<'a>(&'a Cell<u32>);
impl Clone for Counter<'_> {
fn clone(&self) -> Self {
self.0.set(self.0.get() + 1);
Self(self.0)
}
}
fn main() {
let n = Cell::new(0);
let arr = [Counter(&n), Counter(&n), Counter(&n)];
arr.iter().cloned().for_each(drop);
println!("`Counter::clone` called {} times", n.get());
}
`Counter::clone` called 3 times
. Теперь добавим к определению Counter
аннотацию #[derive(Copy)]
и допишем в main
тот же код, что там есть, но с заменой .cloned()
на copied()
:fn main() {Код теперь выводит:
// ...
let n = Cell::new(0);
let arr = [Counter(&n), Counter(&n), Counter(&n)];
arr.iter().copied().for_each(drop); // изменение в этой строке
println!("`Counter::clone` called {} times", n.get());
}
`Counter::clone` called 3 times
`Counter::clone` called 0 times
Берегите себя и не пишите, пожалуйста, в Clone::clone
что-то помимо собственно клонирования.#[aquamarine]
/// mermaid
/// graph LR
/// s([Source]) --> a[[aquamarine]]
/// r[[rustdoc]] --> f([Docs w/ Mermaid!])
/// subgraph rustc[Rust Compiler]
/// a -. inject mermaid.js .-> r
/// end
///
pub fn example() {}