gpt4 book ai didi

带有模板基类的 C++ std::shared_pointer

转载 作者:搜寻专家 更新时间:2023-10-31 00:09:32 27 4
gpt4 key购买 nike

我正在尝试将派生类作为 std::shared_pointer 传递给一个函数,该函数的参数是具有模板的基类。

这是一个完整的例子:

template <class T>
class Base {
public:
std::string typeName()
{
int status;
char *realName = abi::__cxa_demangle(typeid(T).name(), 0, 0, &status);
std::string ret(realName);

free(realName);

return ret;
}
};

class Derived : public Base<float> {};

我想调用的函数是带有共享指针的“doSomething”。

template <class V>
void doSomethingNotShared(Base<V> *test)
{
std::cout << "Not shared type: " << test->typeName() << std::endl;
};

template <class V>
void doSomething(std::shared_ptr<Base<V>> test)
{
std::cout << "Shared type: " << test->typeName() << std::endl;
};

这里是 main 函数,展示了我想如何使用它并指出编译错误。

int main()
{

std::shared_ptr<Derived> testval1 = std::shared_ptr<Derived> (new Derived());
doSomething(testval1); // <- Compilation error

Derived *testval2 = new Derived();
doSomethingNotShared(testval2);

std::shared_ptr<Base<float>> testCast = std::dynamic_pointer_cast<Base<float>>(testval1); // Would rather not have to do this if there is another way ...
doSomething(testCast); // <- No error runs fine
}

有什么方法可以使 doSomething(testval1); 有效吗? ?我希望不必使用 dynamic_pointer_cast (或任何其他类型的类型转换机制)并仅使用 Derived。

主要错误是:std::shared_ptr<Derived> is not derived from std::shared_ptr<Base<V> >

我可以创建一个“AnyBase”类来删除模板参数,但这样会删除我在实际应用程序中设置的一些类型安全,这是必须的。

我正在考虑的一件事是在新类 AnyBase 之间创建一个映射和 std::shared_ptr<AnyBase> , 然后使用函数 doSomethingNotShared用于处理类型安全,并使用查找映射来获取 shared_ptr。 (见下文)

std::map<AnyBase *, std::shared_ptr<AnyBase>> 

编辑:

从我的应用程序中检查类型安全的示例:

template <class V, class W, class X>
void addRuleEdge(Bookkeeper<V> *bookkeeper, std::shared_ptr<IRule<V, W>> rule, ITask<W, X> *consumer)

在这种情况下,我想在 Bookkeeper 之间匹配类型对于 V在第一个模板类型中 IRuleIRule 的第二个模板参数的匹配类型( W ) 第一个模板类型为 ITask .这用作用户的 API 调用,以确保在添加边缘时类型在编译时正确排列。

最佳答案

一个简单的解决方案是更改 doSomething 以处理更广泛的参数集。

template <class V>
void doSomething(std::shared_ptr<V> test)
{
std::cout << "Shared type: " << test->typeName() << std::endl;
};

编辑:使用您的最新示例,我编写了一个示例,说明您如何通过更广泛的重载和 std::enable_ifstatic_assert 实现您想要的。我提供了空类以允许示例编译。

#include <memory>

template<class V>
class Bookkeeper {};

template<class V, class W>
class IRule {};

// Some rule class derived from IRule compatible with Bookkeepr
class RealRule : public IRule<int, float> {};

template<class W, class X>
class ITask {};

// Some task class derived from ITask, compatible with RealRule
class RealTask : public ITask<float, double> {};

// Some task class derived from ITask, not compatible with RealRule
class BadTask : public ITask<int, double> {};

template <class V, class Rule, class W, class X>
typename std::enable_if<std::is_base_of<IRule<V, W>, Rule>::value, void>::type
addRuleEdge(Bookkeeper<V> *bookkeeper, std::shared_ptr<Rule> rule, ITask<W, X> *consumer)
{
// Do work
}

int main()
{
Bookkeeper<int> my_book_keeper;
auto my_rule = std::make_shared<RealRule>();
RealTask my_task;

// Compiles
addRuleEdge(&my_book_keeper, my_rule, &my_task);

BadTask bad_task;

// Won't compile (no matching overload)
addRuleEdge(&my_book_keeper, my_rule, &bad_task);
}

如果您只是想在使用错误类型时收到通知,您也可以选择使用 static_assert

template <class V, class Rule, class W, class X>
void addRuleEdge(Bookkeeper<V> *bookkeeper, std::shared_ptr<Rule> rule, ITask<W, X> *consumer)
{
static_assert(std::is_base_of<IRule<V, W>, Rule>::value, "Type mismatch!");
// Do work
}

int main()
{
Bookkeeper<int> my_book_keeper;
auto my_rule = std::make_shared<RealRule>();
RealTask my_task;

// Compiles
addRuleEdge(&my_book_keeper, my_rule, &my_task);

BadTask bad_task;

// Won't compile (error "Type mismatch!")
addRuleEdge(&my_book_keeper, my_rule, &bad_task);
}

关于带有模板基类的 C++ std::shared_pointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42565239/

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