gpt4 book ai didi

rust - 特征是否有可能返回由特征的泛型类型指定的特征对象?

转载 作者:行者123 更新时间:2023-11-29 08:17:55 25 4
gpt4 key购买 nike

我想定义这样一个特征:

pub trait Provider<T> {
fn load(&self, name: &str) -> Box<dyn T>;
}

但这是不可能的:

error[E0404]: expected trait, found type parameter `T`
--> src/lib.rs:2:47
|
2 | fn load(&self, name: &str) -> Box<dyn T>;
| ^ not a trait

一个可能的解决方案是删除 dyn 关键字,但我希望 Provider 的实现者返回特征对象,如下所示:

pub struct MaterialProvider {}

trait Material {}

impl Provider<Material> for MaterialProvider {
fn load(&self, name: &str) -> Box<dyn Material> { /*...*/ }
}

是否可以表达这样一个概念?

我想用它来创建一个单一的“资源库”,它可以用来创建不同类型的对象。在编译时可能不知道应该支持的确切类型,并且它们不一定需要实现相同的接口(interface)。

在 C++ 中,解决上述问题的一种方法是这样的:

#include <iostream>
#include <map>

class A {
public:
static std::string identifier() {
return "A";
}
};

class B {
public:
static std::string identifier() {
return "B";
}
};

class ProviderBase {};

template <typename T>
class Provider : public ProviderBase {
public:
virtual T* load() = 0;
};

class ProviderA : public Provider<A> {
public:
A* load() {
return new A;
}
};

class Manager {
std::map<std::string, ProviderBase*> providers;

public:
template<typename T>
void register_provider(Provider<T>* provider) {
providers[T::identifier()] = provider;
}

template<typename T>
T* load() {
auto p = providers.find(T::identifier());

if (providers.end() != p) {
return static_cast<Provider<T>*>(p->second)->load();
}

return nullptr;
}
};

int main(int argc, char* argv[]) {
Manager m;

ProviderA provider_a;

m.register_provider(&provider_a);

if (m.load<A>()) {
std::cout << "Loaded A" << std::endl;
} else {
std::cout << "Could not load A" << std::endl;
}

if (m.load<B>()) {
std::cout << "Loaded B" << std::endl;
} else {
std::cout << "Could not load B" << std::endl;
}

return 0;
}

最佳答案

通用特征可以在一个类型上参数化,但不能在另一个特征上参数化。所以在 trait Provider<T> , T是一种类型,而不是特征,这意味着没有 dyn T 这样的东西.

但是,如果类型本身被允许作为特征对象类型,则类型参数应该就是您在这里所需要的全部。为此,您只需取消默认 Sized绑定(bind),因为特征对象未调整大小:

pub trait Provider<T: ?Sized> {
fn load(&self, name: &str) -> Box<T>;
}

pub struct MaterialProvider {}

trait Material {}

impl Provider<dyn Material> for MaterialProvider {
fn load(&self, name: &str) -> Box<dyn Material> { /* ... */ }
}

关于rust - 特征是否有可能返回由特征的泛型类型指定的特征对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56109525/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com