﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-金庆的专栏-随笔分类-8. Rust</title><link>http://www.cppblog.com/jinq0123/category/21420.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 05 Oct 2022 13:26:52 GMT</lastBuildDate><pubDate>Wed, 05 Oct 2022 13:26:52 GMT</pubDate><ttl>60</ttl><item><title>Implementation of user data in cursive::Cursive</title><link>http://www.cppblog.com/jinq0123/archive/2022/10/02/229436.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Sun, 02 Oct 2022 08:38:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2022/10/02/229436.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/229436.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2022/10/02/229436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/229436.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/229436.html</trackback:ping><description><![CDATA[        <h1 id="implementation-of-user-data-in-cursivecursive">Implementation of user data in cursive::Cursive</h1>
<p>(Jin Qing's Column, Oct., 2022)</p>
<p>cursive::Cursive can store any user data:</p>
<pre><code class="language-Rust"><div><span class="hljs-keyword">pub</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Cursive</span></span> {
    ...
    <span class="hljs-comment">// User-provided data.</span>
    user_data: <span class="hljs-built_in">Box</span>&lt;<span class="hljs-keyword">dyn</span> Any&gt;,
}
<span class="hljs-keyword">impl</span> Cursive {
    ...
    <span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">set_user_data</span></span>&lt;T: Any&gt;(&amp;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>, user_data: T) {
        <span class="hljs-keyword">self</span>.user_data = <span class="hljs-built_in">Box</span>::new(user_data);
    }
    <span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">user_data</span></span>&lt;T: Any&gt;(&amp;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>) -&gt; <span class="hljs-built_in">Option</span>&lt;&amp;<span class="hljs-keyword">mut</span> T&gt; {
        <span class="hljs-keyword">self</span>.user_data.downcast_mut()
    }
    <span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">take_user_data</span></span>&lt;T: Any&gt;(&amp;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>) -&gt; <span class="hljs-built_in">Option</span>&lt;T&gt; {
        ...
    }
    <span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">with_user_data</span></span>&lt;F, T, R&gt;(&amp;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>, f: F) -&gt; <span class="hljs-built_in">Option</span>&lt;R&gt;
    <span class="hljs-keyword">where</span>
        F: <span class="hljs-built_in">FnOnce</span>(&amp;<span class="hljs-keyword">mut</span> T) -&gt; R,
        T: Any,
    {
        <span class="hljs-keyword">self</span>.user_data().map(f)
    }
</div></code></pre>
<p>Example:</p>
<pre><code class="language-Rust"><div><span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> siv = cursive_core::Cursive::new();
<span class="hljs-comment">// Start with a simple `Vec&lt;i32&gt;` as user data.</span>
siv.set_user_data(<span class="hljs-built_in">vec!</span>[<span class="hljs-number">1i32</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]);
<span class="hljs-built_in">assert_eq!</span>(siv.user_data::&lt;<span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">i32</span>&gt;&gt;(), <span class="hljs-literal">Some</span>(&amp;<span class="hljs-keyword">mut</span> <span class="hljs-built_in">vec!</span>[<span class="hljs-number">1i32</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]));
<span class="hljs-comment">// Let&#x27;s mutate the data a bit.</span>
siv.with_user_data(|numbers: &amp;<span class="hljs-keyword">mut</span> <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">i32</span>&gt;| numbers.push(<span class="hljs-number">4</span>));
<span class="hljs-comment">// If mutable reference is not enough, we can take the data by value.</span>
<span class="hljs-keyword">let</span> data: <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">i32</span>&gt; = siv.take_user_data().unwrap();
<span class="hljs-built_in">assert_eq!</span>(data, <span class="hljs-built_in">vec!</span>[<span class="hljs-number">1i32</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]);
<span class="hljs-comment">// At this point the user data was removed and is no longer available.</span>
<span class="hljs-built_in">assert_eq!</span>(siv.user_data::&lt;<span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">i32</span>&gt;&gt;(), <span class="hljs-literal">None</span>);
</div></code></pre>
<img src ="http://www.cppblog.com/jinq0123/aggbug/229436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2022-10-02 16:38 <a href="http://www.cppblog.com/jinq0123/archive/2022/10/02/229436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rust sometimes needs manual type annotation</title><link>http://www.cppblog.com/jinq0123/archive/2022/04/29/229301.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 29 Apr 2022 02:14:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2022/04/29/229301.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/229301.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2022/04/29/229301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/229301.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/229301.html</trackback:ping><description><![CDATA[    <h1 id="rust-sometimes-needs-manual-type-annotation">Rust sometimes needs manual type annotation</h1>
    <p>(Jin Qing's Column, Apr., 2022)</p>
    <p>This code compiles error:</p>
    <pre>
      <code>trait MyCallback: FnMut(&amp;u32) -&gt; () { }
impl&lt;F: FnMut(&amp;u32) -&gt; ()&gt; MyCallback for F { }
fn process_data(mut f: impl MyCallback) -&gt; () {
    f(&amp;0)
}
fn process_data_2(mut f: impl FnMut(&amp;u32) -&gt; ()) -&gt; () {
    f(&amp;0)
}
fn main() {
    // Doesn't compile
    process_data(|_| ());
    // Compiles
    process_data_2(|_| ());
}
</code>
    </pre>
    <pre>
      <code>expected type `for&lt;'r&gt; FnMut&lt;(&amp;'r u32,)&gt;`
              found type `FnMut&lt;(&amp;u32,)&gt;`
</code>
    </pre>
    <p>Fix:</p>
    <pre>
      <code>    process_data(|_: &amp;_| ());
</code>
    </pre>
    <p>See: <a href="https://stackoverflow.com/questions/61671460/rust-type-mismatch-resolving-forr-with-closure-trait-alias-argument">https://stackoverflow.com/questions/61671460/rust-type-mismatch-resolving-forr-with-closure-trait-alias-argument</a></p>
    <p>Also see: <a href="https://github.com/rust-lang/rust/issues/58639">https://github.com/rust-lang/rust/issues/58639</a></p>
    <p>Sometimes, Rust needs a type annotation in closure.</p>
<img src ="http://www.cppblog.com/jinq0123/aggbug/229301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2022-04-29 10:14 <a href="http://www.cppblog.com/jinq0123/archive/2022/04/29/229301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How to work around rustup-init failure</title><link>http://www.cppblog.com/jinq0123/archive/2022/04/24/229295.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Sun, 24 Apr 2022 06:09:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2022/04/24/229295.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/229295.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2022/04/24/229295.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/229295.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/229295.html</trackback:ping><description><![CDATA[<h1id="how-to-work-around-rustup-init-failure">How to work around rustup-init failure</h1>
<p>(Jin Qing's Column, Mar., 2022)</p>
<p>rustup-init.exe may fail if some anti-virus software is running with realtime protection.</p>
<p>The error message is like this after many retries:</p>
<pre>
<code>error: could not rename component file from 'C:\.../rust/html' to 'C:\.../rust/html'
</code>
</pre>
<p>See: <ahref="https://github.com/rust-lang/rustup/issues/1912">https://github.com/rust-lang/rustup/issues/1912</a></p>
<p>And it is not possible to stop the anti-virus for a corporate laptop.</p>
<p>There is a way to workaround this. Here are the steps:</p>
<ol>
<li>Run <code>rustup-init</code> until it begins to retry renaming</li>
<li>Kill rustup-init when it is retrying
<ul><li><code>rustup</code> will be installed before the failure</li><li>do not let rustup-init do the cleanup after the final failure</li></ul></li>
<li>Run <code>rustup update</code> to install all.</li>
<li>Run <code>rustup-init</code> again to setup others.</li>
</ol>
<p>
<code>rustup update</code> will report that rustc was not found:</p>
<pre>
<code>C:\Users\jinqing01&gt;rustup update
info: syncing channel updates for 'stable-x86_64-pc-windows-msvc'
...
info: removing previous version of component 'rustc'
warning: during uninstall component rustc was not found
...
info: installing component 'rustc'
...  
info: checking for self-updates
  stable-x86_64-pc-windows-msvc updated - rustc 1.59.0 (9d1b2106e 2022-02-23) (from (rustc does not exist))
info: cleaning up downloads &amp; tmp directories
</code>
</pre>
<p>Rerun <code>rustup-init</code> to setup the toolchain:</p>
<pre>
<code>C:\Users\jinqing01&gt;cargo --version
error: no override and no default toolchain set
C:\Users\jinqing01&gt;d:
D:\&gt;cd tool
D:\Tool&gt;rustup-init.exe
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
...
Rust is installed now. Great!
Press the Enter key to continue.
D:\Tool&gt;cargo --version
cargo 1.59.0 (49d8809dc 2022-02-10)
</code>
</pre>
<img src ="http://www.cppblog.com/jinq0123/aggbug/229295.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2022-04-24 14:09 <a href="http://www.cppblog.com/jinq0123/archive/2022/04/24/229295.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Closure as the function parameter</title><link>http://www.cppblog.com/jinq0123/archive/2022/04/24/229294.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Sun, 24 Apr 2022 06:06:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2022/04/24/229294.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/229294.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2022/04/24/229294.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/229294.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/229294.html</trackback:ping><description><![CDATA[    <h1 id="closure-as-the-function-parameter">Closure as the function parameter</h1>
    <p>(Jin Qing's Column, Mar., 2022)</p>
    <p>It is best to let the function take a closure trait as the parameter instead of a function pointer.</p>
    <pre>
      <code>fn foo(f: fn()) {
    f()
}
fn main() {
    foo(|| println!("hello"));
    let a = 123;
    foo(move || println!("{}", a))
}
</code>
    </pre>
    <p>compiles error:</p>
    <pre>
      <code>error[E0308]: mismatched types
 --&gt; src/main.rs:9:9
  |
9 |     foo(move || println!("{}", a))
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
  |
  = note: expected fn pointer `fn()`
                found closure `[closure@src/main.rs:9:9: 9:34]`
note: closures can only be coerced to `fn` types if they do not capture any variables
 --&gt; src/main.rs:9:32
  |
9 |     foo(move || println!("{}", a))
  |                                ^ `a` captured here
For more information about this error, try `rustc --explain E0308`.
</code>
    </pre>
    <p>
      <a href="https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html">https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html</a>
    </p>
    <blockquote>
      <p>Function pointers implement all three of the closure traits (Fn, FnMut, and FnOnce), so you can always pass a function pointer as an argument for a function that expects a closure. It&#8217;s best to write functions using a generic type and one of the closure traits so your functions can accept either functions or closures.</p>
    </blockquote>
<img src ="http://www.cppblog.com/jinq0123/aggbug/229294.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2022-04-24 14:06 <a href="http://www.cppblog.com/jinq0123/archive/2022/04/24/229294.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Deadlock detection must not run as tokio task</title><link>http://www.cppblog.com/jinq0123/archive/2022/04/24/229293.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Sun, 24 Apr 2022 06:04:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2022/04/24/229293.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/229293.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2022/04/24/229293.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/229293.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/229293.html</trackback:ping><description><![CDATA[<h1 id="deadlock-detection-must-not-run-as-tokio-task">deadlock detection must not run as tokio task</h1>
<p>(Jin Qing's Column, Feb., 2022)</p>
<p>parking_lot has an experimental feature: deadlock_detection.</p>
<p>See: <a href="https://amanieu.github.io/parking_lot/parking_lot/deadlock/index.html">https://amanieu.github.io/parking_lot/parking_lot/deadlock/index.html</a></p>
<pre>
<code>use std::thread;
use std::time::Duration;
use parking_lot::deadlock;
// Create a background thread which checks for deadlocks every 10s
thread::spawn(move || {
loop {
thread::sleep(Duration::from_secs(10));
let deadlocks = deadlock::check_deadlock();
if deadlocks.is_empty() {
continue;
}
println!("{} deadlocks detected", deadlocks.len());
for (i, threads) in deadlocks.iter().enumerate() {
println!("Deadlock #{}", i);
for t in threads {
println!("Thread Id {:#?}", t.thread_id());
println!("{:#?}", t.backtrace());
}
}
}
});
</code>
</pre>
<p>The output is like this:</p>
<pre>
<code>1 deadlocks detected
Deadlock #0
Thread Id 16072
0: 0x7ff985cb659d - backtrace::backtrace::dbghelp::trace
at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.63\src\backtrace\dbghelp.rs:98
...
13: 0x7ff985ae92f3 - lock_api::rwlock::RwLock&lt;parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate&gt;::read&lt;parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate&gt;
at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\lock_api-0.4.6\src\rwlock.rs:448
14: 0x7ff985aeadf3 - cgc::scene::SceneData::check_body_collide
at E:\gitlab\yserver\gc\src\scene.rs:99
...
81: 0x7ff9f29b7034 - BaseThreadInitThunk
82: 0x7ff9f2b02651 - RtlUserThreadStart
</code>
</pre>
<p>But the deadlock detection thread can not be changed to a tokio task,
because if deadlock happens, all tasks may be blocked, including the deadlock detection,
causing no deadlock error output.</p>
<p>In the following example, if the number of the deadlock tasks is larger than the thread number of tokio runtime,
all tasks will be blocked.</p>
<pre>
<code>use std::{thread, time::Duration};
use parking_lot::RwLock;
use tokio::time;
#[tokio::main]
async fn main() {
tokio::spawn(async move {
for i in 0..999999 {
println!("{}", i);
time::sleep(Duration::from_secs(1)).await;
}
});
const MAX: i32 = 100;
for _ in 0..MAX {
tokio::spawn(async move {
{
// DEADLOCK!
let a = RwLock::new(());
let _g1 = a.write();
let _g2 = a.write();
}
time::sleep(Duration::from_secs(9999)).await;
});
}
println!("Hello, world!");
thread::sleep(Duration::from_secs(10));
}
</code>
</pre>
<p>The output is:</p>
<pre>
<code>0
Hello, world!
_
</code>
</pre>
<p>If no deadlock, or the number of deadlock tasks is small, the output should be:</p>
<pre>
<code>0
Hello, world!
1
2
3
...
</code>
</pre>
<img src ="http://www.cppblog.com/jinq0123/aggbug/229293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2022-04-24 14:04 <a href="http://www.cppblog.com/jinq0123/archive/2022/04/24/229293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tracing usage</title><link>http://www.cppblog.com/jinq0123/archive/2022/01/02/218556.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Sun, 02 Jan 2022 04:38:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2022/01/02/218556.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/218556.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2022/01/02/218556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/218556.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/218556.html</trackback:ping><description><![CDATA[<h1 id="tracing-usage">Tracing usage</h1>
    <p>(Jin Qing's Column, Jan., 2022)</p>
    <p>Tracing is Rust log crate: <a href="https://github.com/tokio-rs/tracing">https://github.com/tokio-rs/tracing</a></p>
    <p>This example code outputs log to stdout and a log file, using a log filter config file,
which can be automatically reloaded on change.</p>
    <p>
      <a href="https://gitee.com/jinq0123/tracing-example">https://gitee.com/jinq0123/tracing-example</a>
    </p>
    <h2 id="dependencies">Dependencies</h2>
    <p>Add these dependencies to Cargo.toml:</p>
    <pre>      <code>[dependencies]
anyhow = "1.0.52"
hotwatch = "0.4.6"
tracing = "0.1.29"
tracing-appender = "0.2.0"
tracing-subscriber = { version = "0.3.5", features = [ "env-filter", "json" ] }
</code>
    </pre>
    <h2 id="main.rs">main.rs</h2>
    <pre>      <code class="language-Rust">mod log;
use anyhow::Result;
use std::{thread, time::Duration};
use tracing::info;
fn main() -&gt; Result&lt;()&gt; {
    let _guard = log::init("./log", "example.log", "config/log_filter.txt")?;
    for i in 0..999 {
        info!(i, "Hello, world!");
        thread::sleep(Duration::from_secs(1));
    }
    Ok(())
}
</code>
    </pre>
    <h2 id="log.rs">log.rs</h2>
    <pre>      <code class="language-Rust">//! Init log.
//!
use anyhow::{anyhow, Context as _, Result};
use hotwatch::{Event, Hotwatch};
use std::fs;
use std::path::Path;
use tracing::{debug, warn, Subscriber};
use tracing_appender::{non_blocking::WorkerGuard, rolling};
use tracing_subscriber::{fmt, layer::SubscriberExt, reload::Handle, EnvFilter};
/// Inits log.
/// Returns a WorkerGuard to ensure buffered logs are flushed,
///  and a Hotwatch to watch the log filter file.
pub fn init(
    directory: impl AsRef&lt;Path&gt;,
    file_name_prefix: impl AsRef&lt;Path&gt;,
    log_filter_file: impl AsRef&lt;Path&gt;,
) -&gt; Result&lt;(WorkerGuard, Hotwatch)&gt; {
    let file_appender = rolling::daily(directory, file_name_prefix);
    let (non_blocking, worker_guard) = tracing_appender::non_blocking(file_appender);
    let file_layer = fmt::Layer::default()
        .with_writer(non_blocking)
        .json()
        .flatten_event(true)
        .with_ansi(false);
    let builder = tracing_subscriber::fmt()
        .pretty()
        .with_env_filter(EnvFilter::from_default_env())
        .with_filter_reloading();
    let handle = builder.reload_handle();
    let subscriber = builder.finish();
    let subscriber = subscriber.with(file_layer);
    tracing::subscriber::set_global_default(subscriber).context("set global default subscriber")?;
    reload_filter(handle.clone(), log_filter_file.as_ref());
    let log_filter_path_buf = log_filter_file.as_ref().to_path_buf();
    let mut hotwatch = Hotwatch::new().context("hotwatch failed to initialize!")?;
    hotwatch
        .watch(log_filter_file.as_ref(), move |event: Event| {
            debug!("log filter file event: {:?}", event);
            if let Event::Write(_) = event {
                reload_filter(handle.clone(), log_filter_path_buf.clone());
            }
        })
        .with_context(|| format!("failed to watch file: {:?}", log_filter_file.as_ref()))?;
    Ok((worker_guard, hotwatch))
}
fn reload_filter&lt;S: Subscriber + 'static&gt;(
    handle: Handle&lt;EnvFilter, S&gt;,
    log_filter_file: impl AsRef&lt;Path&gt;,
) {
    let res = try_reload_filter(handle, log_filter_file);
    match res {
        Ok(_) =&gt; debug!("reload log filter OK"),
        Err(e) =&gt; warn!("reload log filter error: {:?}", e),
    }
}
fn try_reload_filter&lt;S: Subscriber + 'static&gt;(
    handle: Handle&lt;EnvFilter, S&gt;,
    log_filter_file: impl AsRef&lt;Path&gt;,
) -&gt; Result&lt;()&gt; {
    let contents = fs::read_to_string(log_filter_file.as_ref()).with_context(|| {
        format!(
            "something went wrong reading the file: {:?}",
            log_filter_file.as_ref()
        )
    })?;
    let contents = contents.trim();
    debug!("reload log filter: {:?}", contents);
    let new_filter = contents
        .parse::&lt;EnvFilter&gt;()
        .map_err(|e| anyhow!(e))
        .context("failed to parse env filter")?;
    handle.reload(new_filter).context("handle reload error")
}
</code>
    </pre>
    <h2 id="log_filter.txt">log_filter.txt</h2>
    <p>log_filter.txt is the configure file for log.
The change of this file will trigger the reload.</p>
    <p>The log filter file must exist, otherwise it will be error:</p>
    <pre>      <code>Error: failed to watch file: "config/log_filter.txt"
Caused by:
    系统找不到指定的路径。 (os error 3)
</code>
    </pre>
    <p>The content of log_filter.txt is a single line of filter string.
A filter string consists of one or more comma-separated directives.
The directive syntax is similar to <a href="https://docs.rs/env_logger/0.9.0/env_logger/#enabling-logging">RUST_LOG env val of env_logger&#8217;s</a>.</p>
    <pre>      <code>target[span{field=value}]=level
</code>
    </pre>
    <p>See: <a href="https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html">https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html</a></p>
    <h3 id="example">Example</h3>
    <ul>
      <li>
        <code>tracing_example</code> enables logs that:
<ul><li>target is modules of <code>tracing_example*</code></li></ul></li>
      <li>
        <code>info</code> will enable logs that:
<ul><li>level is <code>info</code></li></ul></li>
      <li>
        <code>tracing_ex=info</code> enables logs that:
<ul><li>target is modules of tracing_ex*</li><li>level is info or above</li></ul></li>
      <li>
        <code>info,tracing_ex=debug</code> enables logs that:
<ul><li>level is info or above</li><li>or target is tracing_ex* and level is debug</li></ul></li>
      <li>
        <code>[foo]=trace</code> enables logs that:
<ul><li>within the span <code>foo</code></li><li>level is trace or above</li></ul></li>
      <li>
        <code>[span_b{name=\"bob\"}]</code> enables logs that:
<ul><li>have any target,</li><li>are inside a span named span_b,</li><li>which has a field named name with value bob,</li><li>at any level.</li></ul></li>
    </ul>
    <p>Note: span filter directive will keep effective until it exits the span.</p><img src ="http://www.cppblog.com/jinq0123/aggbug/218556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2022-01-02 12:38 <a href="http://www.cppblog.com/jinq0123/archive/2022/01/02/218556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Box&lt;dyn Trait&gt; doesn't implement the trait</title><link>http://www.cppblog.com/jinq0123/archive/2021/12/21/217886.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Tue, 21 Dec 2021 07:09:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/12/21/217886.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217886.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/12/21/217886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217886.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217886.html</trackback:ping><description><![CDATA[<p>&nbsp;From:&nbsp;<a href="https://bennetthardwick.com/dont-use-boxed-trait-objects-for-struct-internals/">Don't use boxed trait objects (bennetthardwick.com)</a></p><p style="box-sizing: border-box; font-family: Rubik, &quot;PT Serif&quot;, system-ui, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Fira Sans&quot;, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">By default a&nbsp;<code style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em; background: rgba(0, 0, 0, 0.04); padding: 0.2em 0px;">Box&lt;dyn Trait&gt;</code>&nbsp;doesn't implement the trait of the object it contains. This means that trying to construct&nbsp;<code style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em; background: rgba(0, 0, 0, 0.04); padding: 0.2em 0px;">PeopleZoo&lt;Box&lt;dyn Person&gt;&gt;</code>&nbsp;won't work out of the box and will give a type error.</p><p style="box-sizing: border-box; font-family: Rubik, &quot;PT Serif&quot;, system-ui, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Fira Sans&quot;, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">Because of this, it's good practice to give a default implementation of your trait for it's boxed counterpart. This can be done by calling&nbsp;<code style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em; background: rgba(0, 0, 0, 0.04); padding: 0.2em 0px;">as_ref</code>&nbsp;or&nbsp;<code style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em; background: rgba(0, 0, 0, 0.04); padding: 0.2em 0px;">as_mut</code>&nbsp;on the&nbsp;<code style="box-sizing: border-box; font-family: monospace, monospace; font-size: 1em; background: rgba(0, 0, 0, 0.04); padding: 0.2em 0px;">Box</code>&nbsp;and calling the references relevant method.</p><p style="box-sizing: border-box; font-family: Rubik, &quot;PT Serif&quot;, system-ui, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Fira Sans&quot;, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">For just a small bit of effort you can help a bunch of people that may consume your struct.<br /><br /></p><p style="box-sizing: border-box; font-family: Rubik, &quot;PT Serif&quot;, system-ui, -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen, Ubuntu, Cantarell, &quot;Fira Sans&quot;, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"></p><div style="display: inline-block;"><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">trait</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">Person</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">{</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
    </span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">fn</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token function-definition function" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">say_hello</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">(</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&amp;</span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">self</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">)</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">;</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">}</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">

</span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">impl</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">Person</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">for</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">Box</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&lt;</span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">dyn</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">Person</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&gt;</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">{</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
    </span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">fn</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token function-definition function" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">say_hello</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">(</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&amp;</span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">self</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">)</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">{</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
        </span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">self</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">.</span><span class="token function" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">as_ref</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">(</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">)</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">.</span><span class="token function" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">say_hello</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">(</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">)</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
    </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">}</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">}</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
<br /></span></div><p>&nbsp;</p><pre class="language-rust" style="box-sizing: border-box; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; font-size: 16px; overflow: auto; padding: 1em; max-width: 100%; background: #fafafa; color: #383a42; direction: ltr; word-break: normal; line-height: 1.5; tab-size: 2; hyphens: none; margin-top: 0px; margin-bottom: 0px; border-radius: 0.3em;"><code class="language-rust" style="box-sizing: border-box; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; font-size: 1em; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; padding: 0.2em 0px; direction: ltr; word-spacing: normal; word-break: normal; line-height: 1.5; tab-size: 2; hyphens: none;"><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none;">struct</span> <span class="token type-definition class-name" style="box-sizing: border-box; color: #b76b01; background: none;">PeopleZoo</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none;">&lt;</span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none;">P</span><span class="token punctuation" style="box-sizing: border-box; background: none;">:</span> <span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none;">Person</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none;">&gt;</span> <span class="token punctuation" style="box-sizing: border-box; background: none;">{</span>
    people<span class="token punctuation" style="box-sizing: border-box; background: none;">:</span> <span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none;">Vec</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none;">&lt;</span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none;">P</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none;">&gt;</span><span class="token punctuation" style="box-sizing: border-box; background: none;">,</span>
<span class="token punctuation" style="box-sizing: border-box; background: none;">}</span></code></pre><div style="display: inline-block;"><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
</span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">fn</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token function-definition function" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">main</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">(</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">)</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">{</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
  </span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">let</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">mut</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> zoo</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">:</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">PeopleZoo</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&lt;</span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">Box</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&lt;</span><span class="token keyword" style="box-sizing: border-box; color: #a626a4; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">dyn</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">Person</span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">&gt;&gt;</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token operator" style="box-sizing: border-box; color: #4078f2; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">=</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token class-name" style="box-sizing: border-box; color: #b76b01; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">PeopleZoo</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">{</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
    people</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">:</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;"> </span><span class="token macro property" style="box-sizing: border-box; color: #e45649; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">vec!</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">[</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">]</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
  </span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">}</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">;</span><span style="color: #383a42; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre; background-color: #fafafa;">
</span><span class="token punctuation" style="box-sizing: border-box; color: #383a42; background: none; font-family: &quot;Fira Code&quot;, &quot;Fira Mono&quot;, Menlo, Consolas, &quot;DejaVu Sans Mono&quot;, monospace; white-space: pre;">}</span></div><img src ="http://www.cppblog.com/jinq0123/aggbug/217886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-12-21 15:09 <a href="http://www.cppblog.com/jinq0123/archive/2021/12/21/217886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>建议日志 slog 改换 tracing</title><link>http://www.cppblog.com/jinq0123/archive/2021/11/24/217865.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 24 Nov 2021 10:18:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/11/24/217865.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217865.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/11/24/217865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217865.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217865.html</trackback:ping><description><![CDATA[<h1 id='建议日志-slog-改换-tracing'>建议日志 slog 改换 tracing</h1>
<p>(金庆的专栏 2021.11)</p>
<ul>
<li><p>slog 不是立即写盘，最后的几行日志会丢失</p>
<ul>
<li>tracing 不会丢日志</li>
</ul>
</li>
<li><p>slog 不支持运行中动态更改日志等级</p>
<ul>
<li><p>tracing <a href='https://tracing.rs/tracing_subscriber/fmt/struct.collectorbuilder#method.with_filter_reloading'>with_filter_reloading()</a></p>
<ul>
<li>examples/tower-load</li>
</ul>
</li>
</ul>
</li>
<li><p>slog 不支持不同包设置不同日志等级</p>
<ul>
<li>tracing 可单独打开某个模块的日志</li>
</ul>
</li>
<li><p>发现一次 slog panic: <code>panicked at &#39;slog::Fuse Drain: Fatal(Custom { kind: BrokenPipe, error: &quot;The logger thread terminated&quot; })&#39;</code></p>
<ul>
<li><p>搜到相同错误：<a href='https://github.com/mimblewimble/grin/issues/946' target='_blank' class='url'>https://github.com/mimblewimble/grin/issues/946</a></p>
<ul>
<li>别人的解决方法是: 不用slog了</li>
</ul>
</li>
</ul>
</li>
<li><p>slog 主页10月添加推荐使用 tracing</p>
</li>
<li><p>slog 按线程保存上下文，tracing 按协程保存上下文</p>
</li>
<li><p>tracing github star 1.9K &gt; slog 1.2K</p>
</li>
<li><p>tracing crates 下载 21M &gt; sloggers 0.4M, slog-scope 2.6M, slog-stdlog 1.9M</p>
</li>
<li><p>tracing vs slog: <a href='https://www.reddit.com/r/rust/comments/kdo29n/slog_vs_tracing_which_one_do_you_prefer/' target='_blank' class='url'>https://www.reddit.com/r/rust/comments/kdo29n/slog_vs_tracing_which_one_do_you_prefer/</a></p>
</li>
<li><p>Rust compiler 2020年已改用 tracing：<a href='https://github.com/rust-lang/rust/pull/74726' target='_blank' class='url'>https://github.com/rust-lang/rust/pull/74726</a></p>
</li>
<li><p>tracing 更好用</p>
<ul>
<li>文档及示例更全</li>
<li>支持库更多</li>
</ul>
</li>
</ul>
<img src ="http://www.cppblog.com/jinq0123/aggbug/217865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-11-24 18:18 <a href="http://www.cppblog.com/jinq0123/archive/2021/11/24/217865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Named parameters in Rust</title><link>http://www.cppblog.com/jinq0123/archive/2021/11/18/217862.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Thu, 18 Nov 2021 05:14:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/11/18/217862.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217862.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/11/18/217862.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217862.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217862.html</trackback:ping><description><![CDATA[<h1 id='named-parameters-in-rust'>Named parameters in Rust</h1>
<p>(Jin Qing&#39;s Column, Nov. 18, 2021)</p>
<p>There is no &quot;named function parameters&quot; in Rust,
but there is an idiom for this case.
If a function needs many parameters, we can define a type
with all these parameters as fields, and implement <code>Default</code> trait for this type.
Then we can input this type as the function parameter, 
with some of the fields specified and others using default.</p>
<pre><code>foo(Config {
    a: 123,
    b: bool,
    ...Default::default(),
});
</code></pre>
<img src ="http://www.cppblog.com/jinq0123/aggbug/217862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-11-18 13:14 <a href="http://www.cppblog.com/jinq0123/archive/2021/11/18/217862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rust traits act as generic constraints</title><link>http://www.cppblog.com/jinq0123/archive/2021/11/18/217861.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Thu, 18 Nov 2021 04:51:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/11/18/217861.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217861.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/11/18/217861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217861.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217861.html</trackback:ping><description><![CDATA[<h1 id='rust-traits-act-as-generic-constraints'>Rust traits act as generic constraints</h1>
<p>(Jin Qing&#39;s Column, Nov. 18, 2021)</p>
<p>Rust traits are different from interfaces of C++/Java/Go.</p>
<p>See: <a href='https://stevedonovan.github.io/rustifications/2018/09/08/common-rust-traits.html' target='_blank' class='url'>https://stevedonovan.github.io/rustifications/2018/09/08/common-rust-traits.html</a></p>
<p>Rust traits are mechanism for adding behavior to types.</p>
<p>Traits have 2 modes. One is interface as Java.</p>
<p>Another is generic constraint. Generic functions are defined over types that implemented specific traits.</p>
<p>The &quot;complie-time duck typing&quot; in C++ templates is avoided in Rust.
Rust will reject a type with quack() method as a Duck type.
We must pass a type which implements Duck trait.
But in Go, a type with quack() method is sufficient to be used as a Duck interface.</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/jinq0123/aggbug/217861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-11-18 12:51 <a href="http://www.cppblog.com/jinq0123/archive/2021/11/18/217861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GLIBC_2.29 not found</title><link>http://www.cppblog.com/jinq0123/archive/2021/11/05/217853.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 05 Nov 2021 01:42:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/11/05/217853.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217853.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/11/05/217853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217853.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217853.html</trackback:ping><description><![CDATA[<h1>GLIBC_2.29 not found</h1>
<p>(Jin Qing&#39;s Column, Nov. 4, 2021)</p>
<p>My Rust program failed when running in docker:</p>
<pre><code>root@a26b49c91efb:/myapp# ldd libmyapp_py.so
./libmyapp_py.so: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29&#39; not found (required by ./libmyapp_py.so)
</code></pre>
<p>The problem is because I build in &quot;rust:1.56&quot;, and run in &quot;debian:buster-slim&quot; which is quite old. Run <code>dpkg -l libc-bin</code> shows the libc version is 2.28:</p>
<pre><code>C:\Users\jinqing01&gt;docker run debian:buster-slim dpkg -l libc-bin
Unable to find image &#39;debian:buster-slim&#39; locally
buster-slim: Pulling from library/debian
b380bbd43752: Already exists
Digest: sha256:544c93597c784cf68dbe492ef35c00de7f4f6a990955c7144a40b20d86a3475f
Status: Downloaded newer image for debian:buster-slim
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  libc-bin       2.28-10      amd64        GNU C Library: Binaries
</code></pre>
<p>Using the latest &quot;debian:bookworm-slim&quot; solved the problem.</p>
<p>Dockerfile:</p>
<pre><code>FROM rust:1.56 as chef
RUN cargo install cargo-chef
WORKDIR /myapp
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /myapp/recipe.json recipe.json
# Build dependencies
RUN cargo chef cook --release --recipe-path recipe.json
# Build application
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim AS runtime
WORKDIR /myapp
RUN apt-get update &amp;&amp; apt-get install -y python3 python3-pip &amp;&amp; rm -rf /var/lib/apt/lists/*
RUN pip3 install protobuf
COPY --from=builder /myapp/target/release/*.so /myapp/
COPY --from=builder /myapp/target/release/myapp /myapp/
COPY --from=builder /myapp/tests /myapp/tests
CMD [&quot;myapp&quot;]
</code></pre>
<img src ="http://www.cppblog.com/jinq0123/aggbug/217853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-11-05 09:42 <a href="http://www.cppblog.com/jinq0123/archive/2021/11/05/217853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Advice for Rust library writers about Error</title><link>http://www.cppblog.com/jinq0123/archive/2021/09/02/217805.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Thu, 02 Sep 2021 03:24:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/09/02/217805.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217805.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/09/02/217805.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217805.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217805.html</trackback:ping><description><![CDATA[<h3>Advice for library writers</h3><p style="margin-top: 0px; margin-bottom: 1rem; font-size: 1.125rem; line-height: 1.5; font-family: system-ui, &quot;Helvetica Neue&quot;, Helvetica, sans-serif; background-color: #ffffff;">Idioms for Rust libraries are still forming, but if your library needs to report custom errors, then you should probably define your own error type. It&#8217;s up to you whether or not to expose its representation (like&nbsp;<a href="http://doc.rust-lang.org/std/io/enum.ErrorKind.html" style="color: #0096cc; text-decoration-line: none;"><code>ErrorKind</code></a>) or keep it hidden (like&nbsp;<a href="http://doc.rust-lang.org/std/num/struct.ParseIntError.html" style="color: #0096cc; text-decoration-line: none;"><code>ParseIntError</code></a>). Regardless of how you do it, it&#8217;s usually good practice to at least provide some information about the error beyond just its&nbsp;<code style="color: #222222;">String</code>&nbsp;representation. But certainly, this will vary depending on use cases.</p><p style="margin-top: 0px; margin-bottom: 1rem; font-size: 1.125rem; line-height: 1.5; font-family: system-ui, &quot;Helvetica Neue&quot;, Helvetica, sans-serif; background-color: #ffffff;">At a minimum, you should probably implement the&nbsp;<a href="http://doc.rust-lang.org/std/error/trait.Error.html" style="color: #0096cc; text-decoration-line: none;"><code>Error</code></a>&nbsp;trait. This will give users of your library some minimum flexibility for&nbsp;<a href="https://blog.burntsushi.net/rust-error-handling/#the-real-try-macro" style="color: #0096cc; text-decoration-line: none;">composing errors</a>. Implementing the&nbsp;<code style="color: #222222;">Error</code>&nbsp;trait also means that users are guaranteed the ability to obtain a string representation of an error (because it requires impls for both&nbsp;<code style="color: #222222;">fmt::Debug</code>&nbsp;and&nbsp;<code style="color: #222222;">fmt::Display</code>).</p><p style="margin-top: 0px; margin-bottom: 1rem; font-size: 1.125rem; line-height: 1.5; font-family: system-ui, &quot;Helvetica Neue&quot;, Helvetica, sans-serif; background-color: #ffffff;">Beyond that, it can also be useful to provide implementations of&nbsp;<code style="color: #222222;">From</code>&nbsp;on your error types. This allows you (the library author) and your users to&nbsp;<a href="https://blog.burntsushi.net/rust-error-handling/#composing-custom-error-types" style="color: #0096cc; text-decoration-line: none;">compose more detailed errors</a>. For example,&nbsp;<a href="https://burntsushi.net/rustdoc/csv/1.0.0-beta.5/enum.Error.html" style="color: #0096cc; text-decoration-line: none;"><code>csv::Error</code></a>&nbsp;provides&nbsp;<code style="color: #222222;">From</code>&nbsp;impls for both&nbsp;<code style="color: #222222;">io::Error</code>&nbsp;and&nbsp;<code style="color: #222222;">byteorder::Error</code>.</p><p style="margin-top: 0px; margin-bottom: 1rem; font-size: 1.125rem; line-height: 1.5; font-family: system-ui, &quot;Helvetica Neue&quot;, Helvetica, sans-serif; background-color: #ffffff;">Finally, depending on your tastes, you may also want to define a&nbsp;<a href="https://blog.burntsushi.net/rust-error-handling/#the-result-type-alias-idiom" style="color: #0096cc; text-decoration-line: none;"><code>Result</code>&nbsp;type alias</a>, particularly if your library defines a single error type. This is used in the standard library for&nbsp;<a href="http://doc.rust-lang.org/std/io/type.Result.html" style="color: #0096cc; text-decoration-line: none;"><code>io::Result</code></a>&nbsp;and&nbsp;<a href="http://doc.rust-lang.org/std/fmt/type.Result.html" style="color: #0096cc; text-decoration-line: none;"><code>fmt::Result</code></a>.<br /><br />From:&nbsp;<a href="https://blog.burntsushi.net/rust-error-handling/" style="font-family: verdana, &quot;courier new&quot;; font-size: 14px;">Error Handling in Rust - Andrew Gallant's Blog (burntsushi.net)</a></p><img src ="http://www.cppblog.com/jinq0123/aggbug/217805.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-09-02 11:24 <a href="http://www.cppblog.com/jinq0123/archive/2021/09/02/217805.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How to show the first few errors of rustc</title><link>http://www.cppblog.com/jinq0123/archive/2021/09/01/217804.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 01 Sep 2021 02:55:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/09/01/217804.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217804.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/09/01/217804.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217804.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217804.html</trackback:ping><description><![CDATA[<div style="background-color: #ffffff; font-family: Consolas, &quot;Courier New&quot;, monospace; line-height: 19px; white-space: pre;"><div><span style="color: #800000;font-weight: bold;">#&nbsp;How&nbsp;to&nbsp;show&nbsp;the&nbsp;first&nbsp;few&nbsp;errors&nbsp;of&nbsp;rustc</span></div><br /><div>(Jin&nbsp;Qing's&nbsp;Column,&nbsp;Sep.&nbsp;1,&nbsp;2021)</div><br /><div>When&nbsp;using&nbsp;VS&nbsp;Code&nbsp;to&nbsp;develop&nbsp;Rust,&nbsp;"cargo&nbsp;check"&nbsp;output&nbsp;maybe&nbsp;thousands&nbsp;of&nbsp;lines.</div><div>Use&nbsp;"cargo&nbsp;check&nbsp;--color=always&nbsp;2&gt;&amp;1&nbsp;|&nbsp;head&nbsp;-n100"&nbsp;to&nbsp;limit&nbsp;the&nbsp;output.</div><br /><div><span style="color: #0451a5;">1.</span>&nbsp;Change&nbsp;powershell&nbsp;terminal&nbsp;to&nbsp;cmd,&nbsp;because&nbsp;powershell&nbsp;fails&nbsp;to&nbsp;use&nbsp;pipe</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0451a5;">*</span>&nbsp;Terminal&nbsp;-&gt;&nbsp;New&nbsp;Terminal&nbsp;to&nbsp;open&nbsp;a&nbsp;terminal</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0451a5;">*</span>&nbsp;Open&nbsp;the&nbsp;dropdown&nbsp;list&nbsp;by&nbsp;click&nbsp;the&nbsp;down&nbsp;arrow&nbsp;of&nbsp;"+"&nbsp;on&nbsp;the&nbsp;top-left&nbsp;of&nbsp;terminal</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0451a5;">*</span>&nbsp;Select&nbsp;"Command&nbsp;Prompt"</div><div><span style="color: #0451a5;">2.</span>&nbsp;Type&nbsp;and&nbsp;run&nbsp;command:&nbsp;<span style="color: #800000;">`cargo&nbsp;test&nbsp;2&gt;&amp;1&nbsp;--color&nbsp;always&nbsp;|&nbsp;"d:\Program&nbsp;Files\Git\usr\bin\head.exe"&nbsp;-n100`</span></div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0451a5;">*</span>&nbsp;You&nbsp;should&nbsp;change&nbsp;the&nbsp;path&nbsp;of&nbsp;head.exe</div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/217804.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-09-01 10:55 <a href="http://www.cppblog.com/jinq0123/archive/2021/09/01/217804.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>&amp;'a mut self is restrictive</title><link>http://www.cppblog.com/jinq0123/archive/2021/08/25/217794.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 25 Aug 2021 05:32:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/08/25/217794.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217794.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/08/25/217794.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217794.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217794.html</trackback:ping><description><![CDATA[<div style="background-color: #ffffff; font-family: Consolas, &quot;Courier New&quot;, monospace; line-height: 19px; white-space: pre;"><div><span style="color: #800000;font-weight: bold;">#&nbsp;&amp;'a&nbsp;mut&nbsp;self&nbsp;is&nbsp;restrictive</span></div><br /><div>From&nbsp;https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md#5-if-it-compiles-then-my-lifetime-annotations-are-correct</div><br /><div>```</div><div>#[derive(Debug)]</div><div>struct&nbsp;NumRef&lt;'a&gt;(&amp;'a&nbsp;i32);</div><br /><div>impl&lt;'a&gt;&nbsp;NumRef&lt;'a&gt;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;my&nbsp;struct&nbsp;is&nbsp;generic&nbsp;over&nbsp;'a&nbsp;so&nbsp;that&nbsp;means&nbsp;I&nbsp;need&nbsp;to&nbsp;annotate</div><div>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;my&nbsp;self&nbsp;parameters&nbsp;with&nbsp;'a&nbsp;too,&nbsp;right?&nbsp;(answer:&nbsp;no,&nbsp;not&nbsp;right)</div><div>&nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;some_method(&amp;'a&nbsp;mut&nbsp;self)&nbsp;{}</div><div>}</div><br /><div>fn&nbsp;main()&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;num_ref&nbsp;=&nbsp;NumRef(&amp;5);</div><div>&nbsp;&nbsp;&nbsp;&nbsp;num_ref.some_method();&nbsp;//&nbsp;mutably&nbsp;borrows&nbsp;num_ref&nbsp;for&nbsp;the&nbsp;rest&nbsp;of&nbsp;its&nbsp;lifetime</div><div>&nbsp;&nbsp;&nbsp;&nbsp;num_ref.some_method();&nbsp;//&nbsp;❌</div><div>&nbsp;&nbsp;&nbsp;&nbsp;println!("{:?}",&nbsp;num_ref);&nbsp;//&nbsp;❌</div><div>}</div><div>```</div><br /><div>If&nbsp;we&nbsp;have&nbsp;some&nbsp;struct&nbsp;generic&nbsp;over&nbsp;'a&nbsp;we&nbsp;almost&nbsp;never&nbsp;want&nbsp;to&nbsp;write&nbsp;a&nbsp;method&nbsp;with&nbsp;a&nbsp;&amp;'a&nbsp;mut&nbsp;self&nbsp;receiver.&nbsp;<br />What&nbsp;we're&nbsp;communicating&nbsp;to&nbsp;Rust&nbsp;is&nbsp;"this&nbsp;method&nbsp;will&nbsp;mutably&nbsp;borrow&nbsp;the&nbsp;struct&nbsp;for&nbsp;the&nbsp;entirety&nbsp;of&nbsp;the&nbsp;struct's&nbsp;lifetime".&nbsp;<br />In&nbsp;practice&nbsp;this&nbsp;means&nbsp;Rust's&nbsp;borrow&nbsp;checker&nbsp;will&nbsp;only&nbsp;allow&nbsp;at&nbsp;most&nbsp;one&nbsp;call&nbsp;to&nbsp;some_method&nbsp;<br />before&nbsp;the&nbsp;struct&nbsp;becomes&nbsp;permanently&nbsp;mutably&nbsp;borrowed&nbsp;and&nbsp;thus&nbsp;unusable.&nbsp;<br />The&nbsp;use-cases&nbsp;for&nbsp;this&nbsp;are&nbsp;extremely&nbsp;rare&nbsp;but&nbsp;the&nbsp;code&nbsp;above&nbsp;is&nbsp;very&nbsp;easy&nbsp;for&nbsp;confused&nbsp;beginners&nbsp;to&nbsp;write&nbsp;and&nbsp;it&nbsp;compiles.&nbsp;<br />The&nbsp;fix&nbsp;is&nbsp;to&nbsp;not&nbsp;add&nbsp;unnecessary&nbsp;explicit&nbsp;lifetime&nbsp;annotations&nbsp;and&nbsp;let&nbsp;Rust's&nbsp;lifetime&nbsp;elision&nbsp;rules&nbsp;handle&nbsp;it:</div><br /><div>```</div><div>#[derive(Debug)]</div><div>struct&nbsp;NumRef&lt;'a&gt;(&amp;'a&nbsp;i32);</div><br /><div>impl&lt;'a&gt;&nbsp;NumRef&lt;'a&gt;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;no&nbsp;more&nbsp;'a&nbsp;on&nbsp;mut&nbsp;self</div><div>&nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;some_method(&amp;mut&nbsp;self)&nbsp;{}</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;above&nbsp;line&nbsp;desugars&nbsp;to</div><div>&nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;some_method_desugared&lt;'b&gt;(&amp;'b&nbsp;mut&nbsp;self){}</div><div>}</div><br /><div>fn&nbsp;main()&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;num_ref&nbsp;=&nbsp;NumRef(&amp;5);</div><div>&nbsp;&nbsp;&nbsp;&nbsp;num_ref.some_method();</div><div>&nbsp;&nbsp;&nbsp;&nbsp;num_ref.some_method();&nbsp;//&nbsp;✅</div><div>&nbsp;&nbsp;&nbsp;&nbsp;println!("{:?}",&nbsp;num_ref);&nbsp;//&nbsp;✅</div><div>}</div><div>```</div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/217794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-08-25 13:32 <a href="http://www.cppblog.com/jinq0123/archive/2021/08/25/217794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rust callback idiom</title><link>http://www.cppblog.com/jinq0123/archive/2021/08/24/217793.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Tue, 24 Aug 2021 02:19:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/08/24/217793.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217793.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/08/24/217793.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217793.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217793.html</trackback:ping><description><![CDATA[<div style="background-color: #ffffff; font-family: Consolas, &quot;Courier New&quot;, monospace; line-height: 19px; white-space: pre;"><div><span style="color: #800000;font-weight: bold;">#&nbsp;Rust&nbsp;callback&nbsp;idiom</span></div><br /><div>Code&nbsp;is&nbsp;from:&nbsp;https://stackoverflow.com/questions/41081240/idiomatic-callbacks-in-rust</div><div>and</div><div>https://morestina.net/blog/793/closure-lifetimes-in-rust</div><br /><div>```</div><div>struct&nbsp;Processor&lt;'a&gt;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;callback:&nbsp;Box&lt;dyn&nbsp;FnMut()&nbsp;+&nbsp;'a&gt;,</div><div>}</div><br /><div>impl&lt;'a&gt;&nbsp;Processor&lt;'a&gt;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;new()&nbsp;-&gt;&nbsp;Processor&lt;'a&gt;&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Processor&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;callback:&nbsp;Box::new(||&nbsp;()),</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;set_callback(&amp;mut&nbsp;self,&nbsp;c:&nbsp;impl&nbsp;FnMut()&nbsp;+&nbsp;'a)&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.callback&nbsp;=&nbsp;Box::new(c);</div><div>&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><div>&nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;process_events(&amp;mut&nbsp;self)&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(self.callback)();</div><div>&nbsp;&nbsp;&nbsp;&nbsp;}</div><div>}</div><br /><div>fn&nbsp;simple_callback()&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;println!("hello");</div><div>}</div><br /><div>fn&nbsp;main()&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;_&nbsp;=&nbsp;Processor::new();</div><div>&nbsp;&nbsp;&nbsp;&nbsp;</div><div>&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;p&nbsp;=&nbsp;Processor&nbsp;{</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;callback:&nbsp;Box::new(simple_callback),</div><div>&nbsp;&nbsp;&nbsp;&nbsp;};</div><div>&nbsp;&nbsp;&nbsp;&nbsp;p.process_events();</div><div>&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;s&nbsp;=&nbsp;"world!".to_string();</div><div>&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;callback2&nbsp;=&nbsp;move&nbsp;||&nbsp;println!("hello&nbsp;{}",&nbsp;s);</div><div>&nbsp;&nbsp;&nbsp;&nbsp;p.set_callback(callback2);</div><div>&nbsp;&nbsp;&nbsp;&nbsp;p.process_events();</div><div>}</div><div>```</div><br /><div>Note:</div><div><span style="color: #0451a5;">*</span>&nbsp;"impl&nbsp;FnMut()"&nbsp;can&nbsp;only&nbsp;used&nbsp;in&nbsp;function&nbsp;declaration,&nbsp;not&nbsp;in&nbsp;struct&nbsp;declaration.</div><div><span style="color: #0451a5;">*</span>&nbsp;dyn&nbsp;FnMut()&nbsp;is&nbsp;unsized,&nbsp;so&nbsp;it&nbsp;must&nbsp;be&nbsp;stored&nbsp;in&nbsp;Box</div><div><span style="color: #0451a5;">*</span>&nbsp;set_callback(&amp;mut&nbsp;self,&nbsp;c:&nbsp;impl&nbsp;FnMut())&nbsp;need&nbsp;a&nbsp;lifetime&nbsp;for&nbsp;c&nbsp;to&nbsp;tell&nbsp;compiler&nbsp;that&nbsp;c&nbsp;outlives&nbsp;structure</div><div>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0451a5;">+</span>&nbsp;rustc&nbsp;suggests&nbsp;<span style="color: #800000;">`impl&nbsp;FnMut()&nbsp;+&nbsp;'static`</span>,&nbsp;but&nbsp;that&nbsp;is&nbsp;too&nbsp;restrictive</div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0451a5;">-</span>&nbsp;In&nbsp;most&nbsp;cases,&nbsp;we&nbsp;do&nbsp;not&nbsp;have&nbsp;a&nbsp;static&nbsp;lifetimed&nbsp;callback</div><div><span style="color: #0451a5;">*</span>&nbsp;FnMut()&nbsp;is&nbsp;more&nbsp;restrictive&nbsp;than&nbsp;FnOnce(),&nbsp;but&nbsp;FnOnce()&nbsp;can&nbsp;only&nbsp;be&nbsp;called&nbsp;once</div><div><span style="color: #0451a5;">*</span>&nbsp;set_callback(...)&nbsp;is&nbsp;a&nbsp;template&nbsp;method,&nbsp;because&nbsp;each&nbsp;closure&nbsp;has&nbsp;a&nbsp;different&nbsp;type</div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/217793.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-08-24 10:19 <a href="http://www.cppblog.com/jinq0123/archive/2021/08/24/217793.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rust variable rebinding for closure</title><link>http://www.cppblog.com/jinq0123/archive/2021/08/22/217787.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Sun, 22 Aug 2021 09:25:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2021/08/22/217787.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/217787.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2021/08/22/217787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/217787.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/217787.html</trackback:ping><description><![CDATA[# Rust variable rebinding for closure<br /><br />From: https://rust-unofficial.github.io/patterns/idioms/pass-var-to-closure.html<br /><br />Rust closure captures variables by reference by default.<br />You can use "move" keyword to change to move variables.<br />In most cases, some variables are moved, and some are referenced.<br />We can rebind variables in a separate scope before move to the closure.<br /><br />```<br />use std::rc::Rc;<br /><br />let num1 = Rc::new(1);<br />let num2 = Rc::new(2);<br />let num3 = Rc::new(3);<br />let closure = {<br />&nbsp;&nbsp;&nbsp; // `num1` is moved<br />&nbsp;&nbsp;&nbsp; let num2 = num2.clone();&nbsp; // `num2` is cloned<br />&nbsp;&nbsp;&nbsp; let num3 = num3.as_ref();&nbsp; // `num3` is borrowed<br />&nbsp;&nbsp;&nbsp; move || {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *num1 + *num2 + *num3;<br />&nbsp;&nbsp;&nbsp; }<br />};<br />```<br /><br />Or we can use additional variables to move in the same scope:<br />```<br />let num2_clone = num2.clone();<br />let num3_ref = num3.as_ref();<br />let closure = move || {<br />&nbsp;&nbsp;&nbsp; *num1 + *num2_clone + *num3_ref<br />}<br />```<br /><br />Using separate scope can reuse the variable name, which make the closure body clearer,<br />but need additional indent.<img src ="http://www.cppblog.com/jinq0123/aggbug/217787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2021-08-22 17:25 <a href="http://www.cppblog.com/jinq0123/archive/2021/08/22/217787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>