Nawaz's answer is likely the right solution for most cases. However, if you're trying to do this for many instantiated SomeContainerFromAThirdPartyLib<T>
classes and only a few functions (or an unknown number of instantiations but a fixed number of functions, as might happen if you're writing your own library), there's another way.
Assume we're given the following (unchangeable) code:
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(); }
};
}
We define an adapter class template containing the necessary typedef
s for iterator_traits
and specialize it to avoid problems with pointers:
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*>
{
};
}
Then, for each function we want to be able to call with a SomeContainerFromAThirdPartyLib::iterator
, we define an overload and use 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);
}
We can then use it as follows:
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;
}
You can find a runnable example with the required include
s and using
s at http://ideone.com/gJyGxU. The output:
a=Hello, world
count(a, a + sizeof(a), 'l')=3
count(container.begin(), container.end(), 0)=[in adapter version of count]0
Unfortunately, there are caveats:
- As I said, an overload needs to be defined for each function you plan to support (
find
, sort
, et cetera). This obviously won't work for functions in algorithm
that haven't been defined yet.
- If not optimized out, there may be small run-time performance penalties.
- There are potential scoping issues.
In regards to that last one, the question is in which namespace to put the overload (and how to call the std
version). Ideally, it would be in ThirdPartyLib
so that it could be found by argument-dependant lookup, but I've assumed we can't change that. The next best option is in MyLib
, but then the call has to be qualified or preceded by a using
. In either case the end-user should either use using std::count;
or be careful about which calls to qualify with std::
, since if std::count
is mistakenly used with SomeContainerFromAThirdPartyLib::iterator
, it will obviously fail (the whole reason for this exercise).
An alternative that I do not suggest but present here for completeness would be to put it directly in the std
namespace. This would cause undefined behavior; while it might work for you, there's nothing in the standard that guarantees it. If we were specializing count
instead of overloading it, this would be legal.