我在template<class...>
struct voider { using type = void; };
template<class...Ts>
using void_t = typename voider<Ts...>::type;
template<template<class...> class Test, class Tuple>
struct get_first_pass;
template<template<class...> class Test, class Tuple>
using get_first_pass_t = typename get_first_pass<Test, Tuple>::type;
template<template<class...> class, class, class...>
struct first_pass {};
template<template<class...> class Test, class T0, class...Ts>
struct first_pass<Test, std::enable_if_t<!Test<T0>::value>, T0, Ts...> :
first_pass<Test, void, Ts...>
{};
template<template<class...> class Test, class T0, class...Ts>
struct first_pass<Test, std::enable_if_t<Test<T0>::value>, T0, Ts...> {
using type = T0;
};
template<template<class...> class Test, template<class...> class Tuple, class...Ts>
struct get_first_pass<Test, Tuple<Ts...>> : first_pass<Test, void, Ts...>
{};
template<class Base>
struct is_derived_from {
template<class Derived>
using test = std::is_base_of<std::decay_t<Base>, std::decay_t<Derived>>;
};
template<class Base, class Tuple>
using get_first_derived =
get_first_pass_t<is_derived_from<Base>::template test, Tuple>;
template<class Base, class Tuple>
auto get_from_base(Tuple&& tuple)
-> decltype(std::get< get_first_derived<Base, std::decay_t<Tuple>> >(
std::forward<Tuple>(tuple))) {
return std::get< get_first_derived<Base, std::decay_t<Tuple>> >(
std::forward<Tuple>(tuple));
}
个字符上使用了迭代器:
String
这会引发编译错误:
pub fn is_yelling(message: &str) -> bool {
let letters = message.chars().filter(|c| c.is_alphabetic());
message.chars().any(|c| c.is_alphabetic()) && letters.all(|c| c.is_uppercase())
}
当我error[E0596]: cannot borrow immutable local variable `letters` as mutable
--> src/main.rs:3:51
|
2 | let letters = message.chars().filter(|c| c.is_alphabetic());
| ------- consider changing this to `mut letters`
3 | message.chars().any(|c| c.is_alphabetic()) && letters.all(|c| c.is_uppercase())
| ^^^^^^^ cannot borrow mutably
变得可变时,一切都顺利进行。
我不明白为什么这个必要。 letters
方法不应该改变迭代器。与all
或map
一样,以filter
而不是self
作为参数。
我的reference for map
/ filter
/ all
。
我看到了an issue on the matter,但没有给出任何解释。
答案 0 :(得分:5)
迭代任何需要改变迭代器,因为Iterator::next
需要&mut self
。检查迭代器中的所有值需要迭代,因此Iterator::all
(以及许多类似的方法)也需要&mut self
。
all
方法不应该改变迭代器。
我很想知道如何在没有调用next
的情况下检查迭代器中的每个值。
赞
map
或filter
这些方法返回一个新的迭代器,它们不会调用next
。话虽这么说,他们可以,如果他们想要因为......
以
self
而非mut self
作为参数。
Mutability是变量所有者的属性。这两个函数是等价的:
fn example(mut a: String) {}
fn example(a: String) {
let mut a = a;
}
重要的是,在生成的文档中两者看起来都一样 - 签名中都没有mut
。这是因为它对调用者来说并不重要。
答案 1 :(得分:3)
迭代器方法all
和any
采用可变引用,因为它们将通过使用其元素来修改迭代器(注意next()
也需要&mut self
,因为它固有地修改迭代器的状态)。另外,这些方法是短路的,并不一定消耗迭代器的所有元素。这意味着这些方法可以将迭代器返回给调用者,因此如果需要,可以继续使用它。
let x = vec![1, 2, 5];
let mut it = x.into_iter();
assert!(it.any(|x| x > 1));
assert_eq!(it.next(), Some(5));
map
或filter
的工作方式不同,因为它们是迭代器适配器。一旦被调用,返回的适配器值将拥有底层迭代器,因此需要移动self
。值不必绑定到可变变量即可移动到另一个范围,即使它们稍后在该上下文中被修改。