c++ - 如何将shared_ptr<void>转换为另一种类型?

标签 c++ dependency-injection c++20

我正在尝试构建一个注入(inject)类,该类允许以某个名称注入(inject)任何其他类,以便自动将所述注入(inject)类传递给注入(inject)类的构造函数。这样做的原因是因为注入(inject)类包含一些设置我想要管理的注入(inject)类所需的变量。

目前我有一些这样的代码:

#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键下

如果这不起作用,是否有其他方法可以以可靠的方式自动将变量传递给实例化/函数调用?

最佳答案

.get()不属于那里。 std::dynamic_pointer_cast适用于shared_ptr直接,而不是原始指针。

另外,您想要 std::static_pointer_cast反而。这相当于 static_cast如果您要使用原始指针而不是 std::shared_ptr ,这是正确的选择。 dynamic_cast在指向多态类层次结构中不同(子)对象的指针之间进行转换。 static_cast类型转换 void*到任何其他指针类型,而不影响指针指向哪个对象(假设指针的地址与 T 适当对齐)。

您有责任确保 std::shared_ptr<void>实际上指向 T 类型的对象。否则使用 std::static_pointer_cast<T> 进行强制转换当使用结果指针时,将(极少数异常(exception))导致未定义的行为。

特别是if (!typedInstance)对于 Actor 阵容没有做任何有用的事情。仅当原始 std::shared_ptr<void> 时它才会失败本来就已经空了。如果std::shared_ptr<void>不指向 T 类型的对象,那么强制转换的结果仍然不是(保证是)空指针。

关于c++ - 如何将shared_ptr<void>转换为另一种类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75762735/

相关文章:

java - 通过 Activity 传递对象 (Android)

c# - 如何使用 Ninject 注入(inject)静态属性?

C++:如何组合多个概念?

c++ - 在 64 位机器上注册 C++ DLL

c++ - 为什么一元减去进行整数提升?

c# - C++ 到 C# 端口问题 : How would I deal with a method that has a double* as a parameter?

c++ - 继承时删除重复的模板类型名条目

c# - 单一职责和依赖

c++ - 函数模板和缩写函数模板之间的等价关系

c++ - 协程参数的生命周期是多少