我尝试构建一个注入类,允许任何其他类以一个名称被注入,目的是自动将所述注入类传递给被注入类的构造函数。这样做的原因是因为注入类包含一些变量,这些变量需要设置我希望管理的被注入类。
目前我有一些代码如下:
#include <memory>
#include <string>
#include <stdout>
#include <typeindex>
class Injector {
private:
std::map<std::type_index, std::map<std::string, std::shared_ptr<void>>> instances;
public:
template<class T, typename... Args>
void inject(std::string name, Args&&... args) {
static_assert(std::is_constructible_v<T, Args..., Injector*>, "Cannot construct type with given args");
auto resourcePtr = std::make_shared<T>(std::forward<Args>(args)..., this);
instances[typeid(T)][name] = resourcePtr;
}
template<class T>
T get(std::string name) {
auto nameToTMap = instances.find(typeid(T));
if (nameToTMap == instances.end()) {
return std::nullopt;
}
auto mapInstance = nameToTMap->second;
auto instance = mapInstance.find(name);
if (instance == mapInstance.end()) {
return std::nullopt;
}
// Here is my problem
auto typedInstance = std::dynamic_pointer_cast<T>(instance->second);
if (!typedInstance) {
return std::nullopt;
}
return typedInstance;
}
};
class Foo {
public:
Foo(int x, int y, Injector injector) {
printf("Hello from Foo, %i, %i", x, y);
}
}
int main() {
Injector injector;
injector.inject<Foo>("foo", 1, 2); // Prints "Hello from Foo, 1, 2"
std::shared_ptr<Foo> myFoo = injector.get<Foo>("foo");
return 0;
}
当编译(clang++)时,我得到错误:
error: 'void' is not a class type
_ET* __p = dynamic_cast<_ET*>(__r.get());
^ ~~~~~~~~~
note: in instantiation of function template specialization 'std::__1::dynamic_pointer_cast<Foo, void>' requested here
auto typedInstance = std::dynamic_pointer_cast<T>(instance->second);
我尝试了几种不同的方法(比如使用Injectable
类),但是没有任何效果,所以我想知道类似的方法在C++中是否有效?我知道从shared_ptr<void>
到shared_ptr<T>
的转换总是会得到正确的结果,因为void
ptr存储在map
中的T
键下
如果这不起作用,有没有其他方法可以可靠地自动将变量传递给示例化/函数调用?
1条答案
按热度按时间mspsb9vt1#
.get()
不属于那里。std::dynamic_pointer_cast
直接应用于shared_ptr
,而不是原始指针。另外,您希望使用
std::static_pointer_cast
。这相当于如果您要使用原始指针而不是std::shared_ptr
,则static_cast
是正确的选择。dynamic_cast
在指向不同static_cast
从void*
强制转换为任何其他指针类型,而不影响指针所指向的对象(假设指针的地址对于T
适当地对齐)。您有责任确保
std::shared_ptr<void>
实际上指向T
类型的对象。否则,使用std::static_pointer_cast<T>
进行的强制转换在使用结果指针时将导致未定义的行为(只有极少数例外)。特别是
if (!typedInstance)
对于类型转换没有任何作用,只有当原始的std::shared_ptr<void>
一开始就为空时才会失败,如果std::shared_ptr<void>
没有指向T
类型的对象,那么类型转换的结果仍然不会(保证是)为空指针。