据我所知,从 C++17 开始,某些 STL 数据结构可能“存在”,并且以不完整的类型作为描述存储类型的模板参数。例如,如果类的所有属性(需要的定义)都在单独的 .cpp 文件中实现,我可以使用std::unique_ptr<Incomplete>(虽然我不确定它是否是数据结构)或作为类成员:std::vector<Incomplete>Incomplete
class Incomplete;
using Complete = int;
class Foo {
private:
std::unique_ptr<Incomplete> u_p;
std::vector<Incomplete> v;
std::deque<Incomplete> d;
std::list<Incomplete> l;
std::set<Incomplete> s;
std::unordered_map<Complete, Complete> u_m_cc;
std::unordered_map<Complete, Incomplete> u_m_ci;
std::unordered_map<Incomplete, Complete> u_m_ic;
std::unordered_map<Incomplete, Incomplete> u_m_ii;
public:
// implemented in a separate .cpp which has Incomplete defined:
Foo();
Foo(Foo&&);
Foo& operator=(Foo&&);
Foo(Foo const&);
Foo& operator=(Foo const&);
~Foo();
};
Run Code Online (Sandbox Code Playgroud)
那么,上面列出的哪些数据成员对于这种用法是有效的呢?其他数据结构、智能指针等呢?
如果在没有初始化实际值时调用 的成员函数std::optional,则会抛出 a 。由于它直接派生自,因此您需要或来处理异常。然而,这两种选择对我来说似乎都很悲伤:value()optionalstd::bad_optional_accessstd::exceptioncatch (std::bad_optional_access const&)catch (std::exception const&)
std::exception捕获每一个异常std::bad_optional_access公开实施细节。考虑以下示例:Placement Item::get_placement() const {
// throws if the item cannot be equipped
return this->placement_optional.value();
}
void Unit::equip_item(Item acquisition) {
// lets the exception go further if it occurs
this->body[acquisition.get_placement()] = acquisition;
}
Run Code Online (Sandbox Code Playgroud)
// somewhere far away:
try {
unit.equip_item(item);
} catch (std::bad_optional_access const& exception) { // what is this??
inform_client(exception.what());
}
Run Code Online (Sandbox Code Playgroud)
std::optional因此,要捕获异常,您需要充分了解 的实现中的用法Item,从而获得已知问题的列表。我都不想捕获并重新包装,std::bad_optional_access因为(对我来说)异常的关键部分是在需要之前忽略它们的可能性。这就是我认为正确的方法:
std::exception
<- …Run Code Online (Sandbox Code Playgroud) 看一看:
use std::convert::{From, TryFrom};
fn main() {
let size: usize = 42;
let good: u128 = u128::try_from(size).unwrap(); // works fine
let bad: u128 = u128::from(size); // doesn't compile!
}
Run Code Online (Sandbox Code Playgroud)
据我所知,usize是一个整数类型,它们永远不会超过 128 位。因此,我认为usize -> u128转换不会失败。那么,为什么不u128实现From<usize>呢?
更新:Rust 的文档说:
从 T for U 隐含 In to U for T
虽然usize -> u128看起来不错,u128 -> usize但不是。好的,但为什么没有Into<u128>实现usize呢?
我正在创建std::sync::atomic::Ordering的子集:
use std::sync::atomic::Ordering;
pub enum StoreOrdering {
Relaxed,
Release,
SeqCst
}
impl Into<Ordering> for StoreOrdering {
fn into(self) -> Ordering {
match self {
Self::Relaxed => Ordering::Relaxed,
Self::Release => Ordering::Release,
Self::SeqCst => Ordering::SeqCst
}
}
}
impl std::convert::TryFrom<Ordering> for StoreOrdering {
type Error = (); // HACK
fn try_from(ord: Ordering) -> Result<Self, Self::Error> {
match ord {
Ordering::Relaxed => Ok(Self::Relaxed),
Ordering::Release => Ok(Self::Release),
Ordering::SeqCst => Ok(Self::SeqCst),
_ => Err(())
}
}
}
enum LoadOrdering {
Acquire,
Relaxed,
SeqCst …Run Code Online (Sandbox Code Playgroud) 有没有办法在不使用 Rust 的情况下实现未定义的行为unsafe?
当然,这种行为可以由第三方库封装在“安全”函数中,所以假设我们只使用标准函数。
这是一个错误结构:
#[derive(Debug)]
pub struct Error {
msg: &'static str,
//source: Option<Box<dyn std::error::Error>>, // old
source: Option<Box<dyn std::error::Error + Send>>, // new
}
impl Error {
fn new_caused<E>(msg: &'static str, err: E) -> Self
where
E: 'static + std::error::Error + Send,
{
Self {
msg: msg,
source: Some(Box::from(err)),
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "{}", self.msg) // HACK
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error …Run Code Online (Sandbox Code Playgroud) 有一个库提供了一个通用函数和一些要使用的实现:
#include <iostream>
namespace lib {
struct Impl1 {};
struct Impl2 {};
void process(Impl1) { std::cout << 1; }
void process(Impl2) { std::cout << 2; }
template<typename T> void generalize(T t) { process(t); }
}
Run Code Online (Sandbox Code Playgroud)
我想通过外部代码扩展它。以下是 C++ 允许这样做的方式:
#include <lib.h> // the previous snippet
namespace client {
struct Impl3 {};
void process(Impl3) { std::cout << 3; }
}
int main() { // test
lib::generalize(client::Impl3{}); // it couts 3
}
Run Code Online (Sandbox Code Playgroud)
注意:lib的代码对 的一无所知,client并且不执行动态调度。如何在我的 Rust 代码中实现相同的目标?(如果我不能,是否有类似计划?)
overloading generic-programming open-closed-principle rust argument-dependent-lookup
Let's say I have a piece of code like this:
// Foo.h:
class Incomplete; // the forward-declaration
class Foo {
void bar(Incomplete&); // doesn't really matter
};
Run Code Online (Sandbox Code Playgroud)
// Foo.cpp:
class Incomplete : private Baz {
};
void Foo::bar(Incomplete&) {
}
Run Code Online (Sandbox Code Playgroud)
Is forward-declaring classes like in Foo.h standard-compliant? If it is, since which language version? What about the same for protected inheritance?
c++ standards inheritance forward-declaration private-inheritance
rust ×5
c++ ×3
standards ×2
c++17 ×1
casting ×1
enums ×1
exception ×1
hierarchy ×1
inheritance ×1
option-type ×1
overloading ×1
reusability ×1
size ×1
std ×1
stl ×1
traits ×1
unsafe ×1
unsigned ×1