c++ - 如何表示一组任意长度和类型组合的值?

标签 c++ data-structures

我正在编写代码来分析 n 维数据集。我写了一个代表任意数据集轴的类。每个轴都可以有不同的数据类型,所以我选择使用模板编程。

class BaseAxis
{
};

template <class T>
class Axis : public BaseAxis
{
public:
    Axis(const T &begin, const T &end);

    const T begin;
    const T end;
};

这允许我创建任意类型的新 Axis 对象。用户可以配置一个更高级别的类 NTree,它通过添加正确的轴来表示整个数据集,如下所示:

ntree = new ntree::NTree<float>();
ntree->AddAxis<int>(0, 8);
ntree->AddAxis<float>(-100.0f, 200.0f);

这将创建一个二维 float 据集,整数轴从 0 到 8,浮点轴从 -100.0f 到 200.0f。要从数据集中获取值,您应该能够按如下方式查询数据结构:

ntree->Query(2, 2.5f);

我目前正在尝试弄清楚如何编写这样的函数(或可以表示这些参数的对象),因为它们可以是任意数量和类型。我读过有关 boost::variant 的内容,但我不确定如何在这种情况下应用它,因为我在 C++ 模板和库方面经验不足。

这是 NTree 类代码的相关部分。

template <class T>
class NTree
{
public:
    NTree();
    ~NTree();

    template <class A>
    void AddAxis(const A &start, const A &end);

protected:
    std::vector<BaseAxis*> *axes;
};

template <class T>
template <class A>
void NTree<T>::AddAxis(const A &start, const A &end)
{
    BaseAxis* newAxis = new Axis<A>(start, end);
    this->axes->push_back(newAxis);
}

因此我的问题是:如何表示一组任意长度和类型组合的值?

最佳答案

您可以使用 Typelist 定义您的容器或 variadic templates .这样你就可以在不使用不透明容器的情况下保持强类型安全。您可以从容器添加和远程轴,可能以复制缓冲区为代价。

一个干净的实现可以为每种类型使用专用的分配器和一个代理类来聚合它们。然后,您可以在代理类中拥有一个模板化访问器,该访问器将使用参数将分配器强制转换回并调用它们的访问函数。

这是一个(非常简洁的)N 维容器的实现。在这种情况下,体积由相同维度但不同类型的数组列表定义,因此并不完全符合您的需要,但接近:

 // opaque base class for allocator
 class UnsafeAllocator{...};

 // specialized allocator:
 template<class T>
 class Allocator : public UnsafeAllocator {
      ...
      virtual T& operator[] (const size_t * position) { ... }
 };

 // proxy class for the container:
 template<class TL>
 class Volume {
 protected:
     // each field has its own allocator, allocated in the constructor
     UnsafeAllocator *opaque_allocator[Length<TL>::value];
 public:
     // put a constuctor with the current dimensions here and fill in the array of allocators using the typelist

     // typesafe getter
     template <int index> 
     typename TypeAt<TL, index>::Result &
     get(const std::initializer_list<size_t> &position){
           typedef typename TypeAt<TL, index>::Result FieldType;
           typedef Allocator<FieldType> SafeAllocator;
           SafeAllocator* allocator = dynamic_cast<SafeAllocator *>(opaque_allocator[index]);
           assert(allocator != NULL);
           return (*allocator)[position];
      }
  };

  // usage would be:
  typedef MakeTypeList(float, int, double) types;
  // define a two dimensional volume for each type
  Volume<types> volume({1024,1024});
  // example of typesafe access for the first type at position 0,0:
  float f = volume.get<0>({0,0});

这个实现的主要缺点是你需要在编译时知道所有的类型列表。我不知道这是否是您的规范的一部分。

如果不是,我不认为有任何方法可以在不到处使用不透明代理的情况下拥有可变数量可变类型的容器,这会破坏代码的可读性(可能还有安全性)。

关于c++ - 如何表示一组任意长度和类型组合的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15507473/

相关文章:

c++ - 为什么 auto i = same_const_variable 无法推断出 "const"?

java - 如何在不返回值的情况下显示消息

c - 非常简单的哈希表查询

algorithm - 什么是 Dijkstra 的最小生成树?

C++ mysql setString 不替换准备好的语句中的占位符

c++ - 嵌套节点类运算符重载 < c++

c++ - Freertos 硬故障分析——堆栈寄存器

c++ - 如何解决重载成员函数问题的地址?

c# - 并发子结构是否需要并发?

java - LIFO 堆栈上的序列