Nawaz's answer is likely the right solution for most cases. However, if you're trying to do this for many instantiated SomeContainerFromAThirdPartyLib
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.
Aşağıdaki (değiştirilemez) kodu verdiğimizi varsayalım:
namespace ThirdPartyLib
{
template
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(); }
};
}
iterator_traits
için gerekli typedef
'i içeren bir adaptör sınıfı şablonu tanımlıyoruz ve işaretçilerle ilgili sorunlardan kaçınmak için uzmanlaşıyoruz:
namespace MyLib
{
template
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
class iterator_adapter
{
};
}
Ardından, her bir işlev için SomeContainerFromAThirdPartyLib :: yineleyici
ile arama yapmak istediğimizde, bir aşırı yük tanımlar ve SFINAE kullanırız:
template
typename MyLib::iterator_adapter::difference_type
count(iter begin, iter end, const typename iter::ValueType& val)
{
cout << "[in adapter version of count]";
return std::count(MyLib::iterator_adapter(begin), MyLib::iterator_adapter(end), val);
}
Bunu aşağıdaki gibi kullanabiliriz:
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 container;
cout << "count(container.begin(), container.end(), 0)=";
cout << count(container.begin(), container.end(), 0) << std;
return 0;
}
Çalışabilir bir örneği include
ve kullanarak
s kullanarak http://ideone.com/gJyGxU . Çıktı:
a=Hello, world
count(a, a + sizeof(a), 'l')=3
count(container.begin(), container.end(), 0)=[in adapter version of count]0
Maalesef, uyarılar var:
- Dediğim gibi, desteklemeyi planladığınız her işlev için bir aşırı yüklenmenin tanımlanması gerekir (
find
, sort
, ve cetera). Bu, henüz tanımlanmayan algoritma
işlevlerinde çalışmayacaktır.
- Optimize edilmediyse, küçük çalışma süresi performans cezaları olabilir.
- Potansiyel kapsam belirleme sorunları var.
Sonuncusuyla ilgili olarak, soru isim alanının aşırı yüklenmeyi (ve std
versiyonunu nasıl çağırılacağı) ile ilgilidir. İdeal olarak, ThirdPartyLib
'da argüman bağımlı aramayla bulunabilir, ancak bunu değiştiremeyeceğimizi varsaydım. Sonraki en iyi seçenek MyLib
'dir, ancak aramanın kullanılarak tarafından nitelendirilmesi veya öncesinde yapılması gerekir. Her iki durumda da son kullanıcı, std :: count öğesini kullanarak
kullanmalı veya std ::
ile nitelendirilecek çağrılara dikkat etmelidir, çünkü std: : count
yanlışlıkla SomeContainerFromAThirdPartyLib :: iterator
ile kullanılır, açıkçası başarısız olacaktır (bu alıştırmanın tüm nedeni).
Önerme 'dir, ancak burada eksiksiz olması için bir alternatif, doğrudan std
ad alanına koymak olacaktır. Bu tanımlanmamış davranışa neden olur; Sizin için işe yarayacak olsa da, standardı garanti eden hiçbir şey yoktur. Eğer aşırı yükleme yapmak yerine saymak
konusunda uzmanlaşırsak bu yasal olur.