gpt4 book ai didi

c++ - 模板多态性和unique_ptr

转载 作者:行者123 更新时间:2023-12-03 07:22:39 24 4
gpt4 key购买 nike

我目前正在尝试对管道进行编程,该管道能够处理每个管道元素中的不同类型的数据。现在,我想将unique_ptr与某种模板多态性和模板特化一起使用。

struct Start {}; // Dummy struct

template<typename In, typename Out>
class PipelineElement {
public:
virtual Out process(In in) = 0;
};

// partial template specialization for the first pipeline element
template<typename Out>
class PipelineElement<Start, Out> {
public:
virtual Out process() = 0;
};

class Producer : public PipelineElement<Start, int> {
int process() override { ... }
};
现在,函数应采用部分专用 unique_ptrPipelineElement。但是,以下内容不会与错误消息一起编译:

auto Pipeline::setStart<int>(std::unique_ptr<PipelineElement<Start,int>,std::default_delete<PipelineElement<Start,int>>>)': cannot convert argument 1 from 'std::unique_ptr<Producer,std::default_delete<Producer>>' to 'std::unique_ptr<PipelineElement<Start,int>,std::default_delete<PipelineElement<Start,int>>>

class Pipeline {
template<typename Out>
static auto setStart(std::unique_ptr<PipelineElement<Start, Out>> element) { ... }
};

int main() {
Pipeline::setStart(std::make_unique<Producer>());
}
如果我改用常规指针,它可以编译而不会出现任何错误。
为什么带有普通指针的版本不能编译,而带有智能指针的版本不能编译?
class Pipeline {
template<typename Out>
auto setStart(PipelineElement<Start, Out>* element) { ... }
};

int main() {
Pipeline::setStart(new Producer());
}

最佳答案

PipelineElement没有虚拟析构函数。因此,通过删除指向Producer的指针来删除PipelineElement会导致错误。
编辑:由于@RemyLebeau信息。不幸的是,std::unique_ptr无法解决这个问题。编译问题是因为编译器无法推断setStart的模板参数。注意:请在将来提供真实的错误消息,而不是伪造的错误消息。
推断模板参数的能力是有限的,除了在模板参数搜索过程中进行一些琐碎的转换外,它不会尝试大多数转换形式。如果不想每次都指定模板参数,建议您接受更通用的输入类型并施加基于SFINEA的限制:
在这里,我基于限制输入unique_ptr<T>以使T继承自PipelineElementBase编写了一个示例。

#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;

struct Start {}; // Dummy struct

class PipelineElementBase
{
public:
virtual ~PipelineElementBase() = default;
};

template<typename In, typename Out>
class PipelineElement : public PipelineElementBase
{
public:
~PipelineElement() { cout << "~PipelineElement<In,Out>" << endl; }
virtual Out process(In in) = 0;
};

// partial template specialization for the first pipeline element
template<typename OutParam>
class PipelineElement<Start, OutParam> : public PipelineElementBase
{
public:
using Out = OutParam;
~PipelineElement() { cout << "~PipelineElement<Start,Out>" << endl; }
virtual Out process() = 0;
};

class Producer : public PipelineElement<Start, int>
{
public:
~Producer() { cout << "~Producer" << endl; }
int process() override { return 1; }
};

class Pipeline
{
public:
template<typename PE, std::enable_if_t<std::is_base_of_v<PipelineElementBase, PE>,int> = 0>
static auto setStart(std::unique_ptr<PE> element)
{
using Out = typename PE::Out;
return 1;
}
};

int main()
{
Pipeline::setStart(std::make_unique<Producer>());
return 0;
}

关于c++ - 模板多态性和unique_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64655165/

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