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

jpfvwuh4  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(481)

我尝试构建一个注入类,允许任何其他类以一个名称被注入,目的是自动将所述注入类传递给被注入类的构造函数。这样做的原因是因为注入类包含一些变量,这些变量需要设置我希望管理的被注入类。
目前我有一些代码如下:

#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键下
如果这不起作用,有没有其他方法可以可靠地自动将变量传递给示例化/函数调用?

mspsb9vt

mspsb9vt1#

.get()不属于那里。std::dynamic_pointer_cast直接应用于shared_ptr,而不是原始指针。
另外,您希望使用std::static_pointer_cast。这相当于如果您要使用原始指针而不是std::shared_ptr,则static_cast是正确的选择。dynamic_cast在指向不同static_castvoid*强制转换为任何其他指针类型,而不影响指针所指向的对象(假设指针的地址对于T适当地对齐)。
您有责任确保std::shared_ptr<void>实际上指向T类型的对象。否则,使用std::static_pointer_cast<T>进行的强制转换在使用结果指针时将导致未定义的行为(只有极少数例外)。
特别是if (!typedInstance)对于类型转换没有任何作用,只有当原始的std::shared_ptr<void>一开始就为空时才会失败,如果std::shared_ptr<void>没有指向T类型的对象,那么类型转换的结果仍然不会(保证是)为空指针。

相关问题