Nawaz 的答案可能是大多数情况下的正确解决方案。但是,如果您尝试对许多实例化SomeContainerFromAThirdPartyLib<T>
的类和只有几个函数(或未知数量的实例化但固定数量的函数,这可能会在您编写自己的库时发生)执行此操作,那么还有另一种方法。
假设我们得到以下(不可更改的)代码:
namespace ThirdPartyLib
{
template <typename T>
class SomeContainerFromAThirdPartyLib
{
public:
typedef T ValueType; // not value_type!
// no difference_type
class iterator
{
public:
typedef T ValueType; // not value_type!
// no difference_type
// obviously this is not how these would actually be implemented
int operator != (const iterator& rhs) { return 0; }
iterator& operator ++ () { return *this; }
T operator * () { return T(); }
};
// obviously this is not how these would actually be implemented
iterator begin() { return iterator(); }
iterator end() { return iterator(); }
};
}
我们定义了一个适配器类模板,其中包含必要typedef
的 siterator_traits
并对其进行专门化以避免指针问题:
namespace MyLib
{
template <typename T>
class iterator_adapter : public T
{
public:
// replace the following with the appropriate types for the third party iterator
typedef typename T::ValueType value_type;
typedef std::ptrdiff_t difference_type;
typedef typename T::ValueType* pointer;
typedef typename T::ValueType& reference;
typedef std::input_iterator_tag iterator_category;
explicit iterator_adapter(T t) : T(t) {}
};
template <typename T>
class iterator_adapter<T*>
{
};
}
然后,对于我们希望能够使用 a 调用的每个函数SomeContainerFromAThirdPartyLib::iterator
,我们定义一个重载并使用 SFINAE:
template <typename iter>
typename MyLib::iterator_adapter<iter>::difference_type
count(iter begin, iter end, const typename iter::ValueType& val)
{
cout << "[in adapter version of count]";
return std::count(MyLib::iterator_adapter<iter>(begin), MyLib::iterator_adapter<iter>(end), val);
}
然后我们可以按如下方式使用它:
int main()
{
char a[] = "Hello, world";
cout << "a=" << a << endl;
cout << "count(a, a + sizeof(a), 'l')=" << count(a, a + sizeof(a), 'l') << endl;
ThirdPartyLib::SomeContainerFromAThirdPartyLib<int> container;
cout << "count(container.begin(), container.end(), 0)=";
cout << count(container.begin(), container.end(), 0) << std;
return 0;
}
您可以在http://ideone.com/gJyGxU找到一个带有所需include
s 和using
s的可运行示例。输出:
a=你好,世界
计数(a, a + sizeof(a), 'l')=3
count(container.begin(), container.end(), 0)=[在 count 的适配器版本中]0
不幸的是,有一些警告:
- 正如我所说,需要为您计划支持的每个函数定义一个重载(
find
,,sort
等等)。这显然不适用于algorithm
尚未定义的函数。
- 如果不进行优化,可能会有小的运行时性能损失。
- 存在潜在的范围界定问题。
关于最后一个,问题是在哪个命名空间中放置重载(以及如何调用std
版本)。理想情况下,它ThirdPartyLib
可以通过依赖于参数的查找找到它,但我假设我们无法改变它。下一个最佳选项是 in MyLib
,但是调用必须有限定或前面有 a using
。在任何一种情况下,最终用户都应该使用using std::count;
或注意哪些调用符合条件std::
,因为如果std::count
错误地与 一起使用SomeContainerFromAThirdPartyLib::iterator
,它显然会失败(这个练习的全部原因)。
为了完整起见,我不建议但在这里展示的另一种方法是将其直接放在std
名称空间中。这会导致未定义的行为;虽然它可能对您有用,但标准中没有任何东西可以保证它。如果我们专门count
化而不是重载它,这将是合法的。