gpt4 book ai didi

c++ - 当类型是未知模板参数时使用原始指针

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

目前,我们有一个带有标准组件数组的容器类。这些组件是模板化的,并且派生自非模板化的基类。调用成员函数时一切顺利。

但是,容器类包含模板化类型 T 的原始指针,我们希望在组件和容器类之外使用这些指针。

例如,我在这里给出了一个 std::transform,但我们在代码库和 API 的许多地方都使用了它,但没有 vector 或标准支持。

目前,我们转换原始指针,但那确实是糟糕的设计。我们使用 c++14,所有组件及其类型在编译时都是已知的。

任何想法,即我们可以用什么代替 ???

这是一个最小的例子:

可运行和可编辑的代码也在这里:https://rextester.com/QLP97953

#include <iostream>
#include <memory>
#include <array>
#include <algorithm>

class ComponentInterface{
public:
virtual void DoStuff() = 0;
virtual void* GetPtr() = 0;
static constexpr size_t Size() { return 10; }
};

template <class T> class Component : public ComponentInterface {
public:
Component(const std::array<T, Size()>& arr){for(int i = 0; i < Size(); ++i) ptr[i] = arr[i];}
void DoStuff() override { std::cout << ptr[0] << " " << ptr[1] << " " << ptr[2] << " " << std::endl; }
void* GetPtr() override { return (void*)(ptr); }
private:
T ptr[Size()];
};

class Container{
private:
std::array<std::unique_ptr<ComponentInterface>, 3> components;
public:
Container() {
components[0] = std::unique_ptr<Component<int> >(new Component<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
components[1] = std::unique_ptr<Component<float> >(new Component<float>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
components[2] = std::unique_ptr<Component<double> >(new Component<double>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}));
}
void DoStuff(int i) { components[i]->DoStuff(); }
void* GetPtr(int i) { return components[i]->GetPtr(); }
const size_t Size(int i) { return components[i]->Size(); }
};

int main()
{
Container c;
for(int i = 0; i < 3; ++i)
c.DoStuff(i);

//Works, not a good design
std::transform((int*)c.GetPtr(0), (int*)c.GetPtr(0) + c.Size(0), (int*)c.GetPtr(0), [](int a) -> int { return a + 1; });
std::transform((float*)c.GetPtr(1), (float*)c.GetPtr(1) + c.Size(1), (float*)c.GetPtr(1), [](int a) -> int { return a + 1; });
std::transform((double*)c.GetPtr(2), (double*)c.GetPtr(2) + c.Size(2), (double*)c.GetPtr(2), [](int a) -> int { return a + 1; });

for(int i = 0; i < 3; ++i)
; // ???

for(int i = 0; i < 3; ++i)
c.DoStuff(i);
}

最佳答案

使用访问者模式,而不是向接口(interface)添加方法:

class ComponentInterface{
public:
virtual ~ComponentInterface() = default;

virtual void DoStuff() = 0;
virtual void Method1() = 0;
virtual void Method2() = 0;
virtual void Method3() = 0;

static constexpr size_t Size() { return 10; }
};

假设您知道每个 child 的类型,您可能会这样做:

template <class T> class Component;

struct IVisitor
{
virtual ~IVisitor() = default;

virtual void Visit(Component<int>&) = 0;
virtual void Visit(Component<float>&) = 0;
virtual void Visit(Component<double>&) = 0;
};


class ComponentInterface{
public:
virtual ~ComponentInterface() = default;
virtual void DoStuff() = 0;
virtual void Accept(IVisitor&) = 0;
static constexpr size_t Size() { return 10; }
};

然后

template <class T> class Component : public ComponentInterface {
public:
Component(const std::array<T, Size()>& arr);
void DoStuff() override;
void Accept(IVisitor& visitor) override { visitor.Visit(*this); }
//private:
T ptr[Size()];
};

用法是:

struct IncreaseByOne : IVisitor
{
template <typename T>
void operator() (Component<T>& c)
{
std::transform(std::begin(c.ptr), std::end(c.ptr),
std::begin(c.ptr),
[](auto e) { return e + 1; });
}

void Visit(Component<int>& c) override { (*this)(c); }
void Visit(Component<float>& c) override { (*this)(c); }
void Visit(Component<double>& c) override { (*this)(c); }
};

    IncreaseByOne visitor;
for(int i = 0; i < 3; ++i)
components[i].Accept(visitor);

Demo

关于c++ - 当类型是未知模板参数时使用原始指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57688324/

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