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

时间:2017-12-21 11:14:25

标签: c++ templates

我有一个由模板化类型构成的结构,除非实例化,否则使用不完整的类型,如std::vector。对这些类型的访问适用于类型安全索引包装器。例如:

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);}
};

但现在我需要Holder的完整类型,我想避免。是否可以使用不完整类型和便利功能?也许有些模板会有所帮助,但我需要对foos或bar进行一些调度,这很可能会实例化它。

2 个答案:

答案 0 :(得分:0)

也许你可以创建一个模板功能

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>,因为这需要完全定义的类型(引用允许不完整的类型)。

答案 1 :(得分:0)

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

我需要一个模板化的get函数,因此容器get函数不会在头文件中实例化。因此我们有:

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 :: list(Foo,Bar)
  2. 创建一个包含1 MetaHolder
  3. 的模板化结构MyVector<T>
  4. 让Holder继承自MetaHolder实例化的每种类型
  5. 实现1(!)通用getContainer函数,只返回MetaHolder<T>.container
  6. 所有内容都将在编译时得到解决,因此没有运行时开销。虽然Boost.MPL可能会变得非常繁重,但不确定编译时的开销。