【发布时间】:2016-06-11 10:58:49
【问题描述】:
我开始使用 Rust 开发一个新库。我试图围绕可能的方法来实现以下内容。
接下来更多的是想要的表达,而不是真正的语法。我试图表达这一点的所有方式要么不编译,要么在我去实现一个别名特征时不编译。
struct ConcreteType;
struct CommonType;
trait Handler<Rin, Rout = Rin>{
fn handle_event(&self, msg: &Rin);
}
// alias Handler with one of the types defined as a common case
trait HandlerToMessage<M> : Handler <ConcreteType, M>{
fn handle_event(&self, msg: &ConcreteType) {
// default implementation of parent trait
// example is simplified, forget about how Rout/M is actually used
self.decode(msg)
}
// method to implement
fn decode(&self, msg: &ConcreteType) -> M;
}
// another alias for most common case where Rin/Rout are ConcreteType, CommonType most often
trait HandlerToCommonType : HandlerToMessage <ConcreteType, CommonType>{
fn decode(&self, msg: &ConcreteType) -> CommonType
{
...
};
}
使用关联类型的替代方法
trait Handler{
type Rin;
type Rout; // not yet able to do Rout = Rin with associated types
fn handle_event(&self, msg: &Self::Rin) -> Self::Rout;
}
trait HandlerToMessage : Handler <Rin=ConcreteType>{
fn handle_event(&self, msg: &Self::Rin) {
// common functionality
self.decode(msg)
}
// method to implement
fn decode(&self, msg: &Self::Rin) -> Self::Rout;
}
trait HandlerToCommonType : HandlerToMessage <Rout=CommonType>{
fn decode(&self, msg: &ConcreteType) -> CommonType
{
...
}
}
在 C++ 中,这大致就是我想要完成的目标
// real world example I've seen in the wild of this structure
template <class Rout>
class Context {
public:
void dispatch(Rout* msg);
};
template <class Rin, Rout = Rin>
class ReadHandler {
public:
void read (Context* ctx, Rin* msg) = 0;
private:
Context<Rout> ctx_;
};
// very common to convert from a byte buffer some message type
template <class M>
class BytesToMessageDecoder : ReadHandler<IOBuffer, M> {
public:
// Template method pattern
void read (Context* ctx, IOBuffer* msg) {
M msgOut;
bool success;
success = this->decode(msg, &msgOut);
if (success) {
ctx->dispatch(msgOut);
}
}
bool decode(IOBuffer* msg, M* msgOut) = 0;
}
// convert one byte buffer to another is common
typedef BytesToMessageDecoder<IOBuffer> BytesToBytesDecoder;
// Concrete implementations
// look for fixed number of bytes incoming
class FixedLengthFrameDecoder : BytesToBytesDecoder {
bool decode(IOBuffer* msg, IOBuffer* msgOut) { ... }
}
// fields are prefixed with a length. Wait for that many bytes and then dispatch
class LengthBasedFieldDecoder: BytesToBytesDecoder {
bool decode(IOBuffer* msg, IOBuffer* msgOut) { ... }
}
class StringDecoder : BytesToMessageDecoder<std::string> {
// decode from byte buffer to a string
bool decode(IOBuffer* msg, std::string* msgOut) { ... }
}
基本上顶级特征Handler 是最通用的,但可能不打算由高级库用户以外的任何人实现。 HandlerToMessage 特征是一种常见的转换,我们将ConcreteType 转换为其他类型。该库可以实现其中的几个。 HandlerToCommonType 是许多库类型想要从最常见的情况开始。
Rout 如何在 Handler 特征中使用的细节并不重要。我试图简化这个例子,并留下一些论据,希望能让我想要表达的内容更简洁。我对此的所有搜索要么让我认为这是不可能传达的,要么我在滥用它。我不太明白这是否属于新的专业化实现,但从我的理解来看并不像。
我意识到 Rust 不是 C++,所以也许我正在尝试做的事情要么不受支持,要么具有不同的语法。任何帮助都以正确的语法或更惯用的 Rust 方式表示赞赏。
【问题讨论】:
-
你的第一个例子根本没有使用
Rout。 -
@Shepmaster 我编辑了 C++ 示例以使其更加真实,我希望因为我不肯定我可以在 Rust 中传达这个想法。如果我能以某种方式更清楚,请告诉我。谢谢你一直陪着我,非常感谢。
标签: rust