添加无模板实例化的访问者方法

Add accessor method without template instantiation

本文关键字:访问者 方法 实例化 添加      更新时间:2023-10-16

i具有由模板类型制成的结构,除非实例化,否则与不完整类型一起使用,例如std::vector。访问这些类型的类型使用类型Aftex索引包装器。示例:

template<class T>
struct Idx{unsinged val;};
struct Holder{
MyVector<Foo> foos;
MyVector<Bar> bars;
};
const Foo& foo = holder.foos.get(Idx<Foo>(...));

这效果很好:Idx不需要知道模板参数的类型,因为它从未使用过。持有人也可以与Foo/bar的前瞻性声明一起工作。我不能将Idx<Foo>Idx<Bar>混淆,因为我只能与它们相应的类型。因为这是如此独特,但我将便利功能添加到持有人:

struct Holder{
MyVector<Foo> foos;
MyVector<Bar> bars;
const Foo& get(Idx<Foo> idx) { return foos.get(idx);}
const Bar& get(Idx<Bar> idx) { return bars.get(idx);}
};

,但是现在我需要为持有人提供完整的类型,我想避免使用。是否可以使用不完整的类型和便利功能?也许有些模板有所帮助,但我需要对Foos或最有可能实例化的酒吧进行一些派遣。

也许您可以创建模板函数

template<typename T>
const T& getByIndex(const MyVector<T>& vec, const Idx<T>& idx)
{ return vec.get(idx); }

然后您可以在Holder中使用它,例如

const Foo& get(const Idx<Foo>& idx) { return getByIndex(foos, idx); }

不要指望参数作为实例Idx<Foo>,因为这需要完全定义的类型(参考允许不完整的类型)。

我在讨论的讨论中找到了一个解决方案,然后由 @grek40:

我需要一个模板化的获取功能,以便容器获取功能不会在标题中实例化。因此我们有:

template<class T> const T& get(DescIdx<T> idx) const { return getContainer<T>().get(idx); }

现在我们需要一个简单的getContainer功能:template<class T> const MyVector<T>& getContainer() const;

需要对我们的容器进行实例化:template<> inline const MyVector<Foo>& Holder::getContainer() const { return foos; }

总的来说:

template<class T>
struct Idx{unsinged val;};
struct Holder{
MyVector<Foo> foos;
MyVector<Bar> bars;
template<class T> const T& get(DescIdx<T> idx) const { return getContainer<T>().get(idx); }
template<class T> const MyVector<T>& getContainer() const;
};
template<> inline const MyVector<Foo>& Holder::getContainer() const { return foos; }
template<> inline const MyVector<Bar>& Holder::getContainer() const { return bars; }
// Somewhere else
const Foo& foo = holder.get(Idx<Foo>(...));

使用模板元编程可以改善这一点。步骤:

  1. 定义一个boost :: mpl ::所有类型的列表(foo,bar)
  2. 创建一个存放1 MyVector<T>
  3. 的模板结构MetaHolder
  4. 让持有人从每种类型实例化的MetaHolder继承
  5. 实现1(!)通用getContainer函数,只需返回MetaHolder<T>.container

在编译时一切都会解决,因此没有运行时开销。不确定要编译时间开销,因为boost.mpl会变得很重。