我正在尝试编写一个包含多个 std::vectors 作为数据成员的类,并提供向量接口的子集来访问它们:
class Mesh
{
public:
private:
std::vector<Vector3> positions;
std::vector<Vector3> normals;
// Several other members along the same lines
};
您可以使用网格做的主要事情是向其中添加位置、法线和其他内容。为了允许以类似 STL 的方式访问网格(从数组、其他容器等添加),我正在考虑添加如下方法:
public:
template<class InIter>
void AddNormals(InIter first, InIter last);
问题是,根据我对模板的理解,这些方法必须在头文件中定义(似乎是有道理的;如果没有具体的迭代器类型,编译器不知道如何生成目标代码来明显实现这个方法)。
这实际上是一个问题吗?我的直觉反应是不会在头文件中粘贴大量代码,但我的 C++ 有点生疏,除了玩具示例之外没有太多 STL 经验,而且我不确定在这方面什么是“可接受的”C++ 编码实践。
有没有更好的方法来公开此功能,同时保留类似 STL 的通用性
编程风格?一种方法是这样的:
(最终名单)
class RestrictedVector<T>
{
public:
RestrictedVector(std::vector<T> wrapped)
: wrapped(wrapped) {}
template <class InIter>
void Add(InIter first, InIter last)
{
std::copy(first, last, std::back_insert_iterator(wrapped));
}
private:
std::vector<T> wrapped;
};
然后在 Mesh 上公开这些实例,但这开始散发出一点过度设计的味道:P 非常感谢任何建议!
这些方法必须在头文件中定义
它们必须定义在a头文件,这样如果使用它们,那么它们就可以在实例化模板函数的翻译单元中使用。如果您担心头文件中的模板太多,会减慢使用 Mesh 但实际上不使用该模板函数的翻译单元的编译速度,那么您可以将实现移至单独的头文件中。让客户的生活稍微复杂一些,决定是否包含“full fat”类标头,但这实际上并不困难。
或者,对于这个特定的示例,您可以为网格定义一个输出迭代器,它会附加法线。然后具有任意迭代器的客户端可以执行以下操作:
std::copy(first, last, mymesh.normalAdder());
他们需要的唯一包含模板代码的标头是<algorithm>
,他们很可能已经拥有了。
要自己做,返回的对象normalAdder()
需要超载operator++()
and operator*()
,它本身需要返回一个代理对象(通常*this
)它实现了operator=(const &Vector3)
。这附加到法线向量上。但所有这些都是非模板代码,可以在您的 .cpp 文件中实现。
再次在这个例子中,normalAdder()
可以回来std::back_inserter(this.normals);
,一个模板来自<iterator>
.
至于您是否需要担心它 - 我认为当编译时间急剧增加时,更常见的是由于不必要的依赖项,而不是由于标头中的少量模板代码。一些大型项目似乎需要采取严厉措施,但就我个人而言,我还没有处理过超过 100 个左右的文件。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)