我有一个由模板化类型构成的结构,除非实例化,否则使用不完整的类型,如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进行一些调度,这很可能会实例化它。
答案 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>(...));
这可以通过使用模板元编程来改进。步骤进行:
MetaHolder
MyVector<T>
MetaHolder
实例化的每种类型MetaHolder<T>.container
。所有内容都将在编译时得到解决,因此没有运行时开销。虽然Boost.MPL可能会变得非常繁重,但不确定编译时的开销。