处理特定类型元素的任何容器的非模板函数

Ole*_*nov 3 c++ containers templates iterator

我想要一个标题中描述的功能。

我注意到,与包含任何类型(int、double)元素的任何类型(列表、向量等)容器一起工作的 STL 算法通过使用迭代器类型作为模板参数来提供通用性,例如

template<typename _II, typename _OI>
inline _OI
copy(_II __first, _II __last, _OI __result)
Run Code Online (Sandbox Code Playgroud)

这是一个很好的方法,直到该算法适用于任何类型的元素。元素类型的唯一要求是它必须具有复制构造函数。

但是假设我们有一个具体的类型

class MyElement
{
    public:
    void doSomethingWithElement();
};
Run Code Online (Sandbox Code Playgroud)

并且我们想通过调用 function 来实现一个处理这种类型元素数量的函数doSomethingWithElement()

编写一个接收特定类型容器的函数不是很方便,因为许多容器以相同的方式处理(例如迭代器),如果需要处理不同类型的容器,我们将被迫复制代码。编写模板工作正常,但它看起来很丑,因为我们必须在声明它的地方(在头文件中)实现函数。此外,当我们只想处理一种类型的元素时,参数化这种类型并不是实现目标的正确方法。

我一直在考虑可以像这样使用的迭代器接口

void processContainer(IIterator<MyElement> begin, IIterator<MyElement> end);
Run Code Online (Sandbox Code Playgroud)

如果这个迭代器具有在派生类中实现的纯虚 operator++ 和 operator*,我们可以将这些对象传递给processContainer. 但是有一个问题:如果IIterator是抽象类,我们不能在实现中实例化它processContainer,如果我们传递一个指针给IIterator,这个函数就可以修改它。

有没有人知道任何其他黑客来做到这一点?或者是比上面这些更好的另一种方法?提前致谢。

Dav*_*eas 5

更简单的方法是忽略限制,并将您的函数实现为任何迭代器的模板。如果迭代器不引用类型,那么用户将在“类型 X 没有doSomethingWithElement成员函数”的行中收到可怕的错误消息。

接下来是提供 a static_assert,该函数仍将采用任何迭代器(意味着它将参与任何类型的重载解析),但错误消息将提供更多信息。

此外,您可以决定使用 SFINAE 从候选集中删除过载。但是,虽然 SFINAE 是一把漂亮的金锤,但我不确定您手头是否有合适的钉子。

如果您真的想走得更远,您可以查看any_iteratorAdobe 库中的示例,了解如何对迭代器类型执行类型擦除以避免模板。这种方法的复杂性比以前的任何一种都高几个数量级,运行时成本也会更高,唯一的优点是更干净的 ABI 和更少的代码大小(可以将不同的迭代器传递给单个函数)。