2010-06-10 25 views
15

Bu ilişkili yineleyicileri almak için bir kap verilen örnek kolay konteyner türü elde "karşılık gelen kapsayıcı" türünü çıkarmak için (burada her kapsayıcı için bir tane ve bir tane (const olmayan) yineleyicinin olduğunu varsayarak). Daha kesin olarakC (kendi) yineleyici türü ++ (STL)

ben, örneğin, bu tür (her bir kap için el ile uzmanlaşmış zorunda kalmadan) tüm STL taşıyıcı ile çalışan bir kalıp üst-işlevin eder:

ContainerOf< std::vector<double>::iterator >::type 

std::vector<double> 
olarak değerlendirilirse

Mümkün mü? Değilse, neden?

Yardımlarınız için şimdiden teşekkür ederiz! C++ STL Yineleyicilerin

+2

bir Yineleyiciyi konsepsiyonuna öğrenmek için çalışıyorsun ? yani rastgele erişim ise? STL bunun için etiketler kullanır. Genellikle bir yineleyici nereden geldiğini bilmek için bir neden yoktur. – pmr

+0

7 STL konteynırlarından birinde bir yineleyici olup olmadığını biliyor musunuz, yoksa "else" maddesine de ihtiyacınız var mı? – MSalters

cevap

7

Bunun mümkün olacağını düşünmüyorum. Bazı STL kitaplıklarında, bir işaretçi türü olarak i.e. std::vector<T>::iterator is a T* numaralı bir vektör yineleyiciniz vardır, bu yüzden kapsayıcı türüne geri dönebilmenizi hiçbir şekilde düşünemiyorum.

+0

Ancak, bu başka bir STL konteynerinin yineleyicisi olamaz. Sadece 7 tane var ve hepsini bir araya getirebilirsin. – MSalters

+0

Bu adil bir nokta. Harita ve multimap arasındaki fark nasıl olsa? Bunları karşılaştırma operatöründen ayırabilir misiniz? – Hitobat

+0

Bu çekilse olabilir, eğer yapı 'std :: iterator_traits T container_type typedef ' gerekenler ';' kendi 'std yapabilir ancak :: iterator_traits_pro' böyle typedef. – k06a

0

tam çalışma zamanı türleri kasıtlı tanımlanmamış ve bu nedenle uygulama özeldir. Aslında hangi türün kullanıldığını bulmak için derleyici sağlayıcınızın başlık dosyalarını arayabilir ve kapsayıcıyı buradan çıkartabilirsiniz, ancak satıcı ve sürüme özgüdür, dolayısıyla kırılmaya eğilimlidir.

+0

Cevabınız için teşekkürler! Şimdi sorunumun kasıtlı olarak "çözülebilir" olmadığından eminim. – stepelu

0

Yineleyicilerin noktası bir başlangıcı/sonu çiftini geçen örneğin, altta yatan konteyner türünü bilmek zorunda ve bu dizi iş yapmadan işi yapmak için kullanabilirsiniz olmasıdır. önemsediğiniz tüm yineleyici türüyse

Ancak, ben bir yineleyici rasgele erişim ise örneğin belirlemek için yineleyici özellikleri kullanabilirsiniz inanıyoruz. std::advance'u ele alın, genel durum, yineleyici n kez operator++'u çağırmasıdır, ancak rastgele erişim yineleyicileri için + = yerine kullanmak üzere uzmanlaşmıştır. Bunun dışında

ben İlerleticiden konteyner tipini almak için herhangi bir şekilde farkında değilim.

+0

Bu, etiket gönderimi yoluyla gerçekleştirilir. http://www.boost.org/community/generic_programming.html#tag_dispatching –

5

Sadece eğlence için, burada hızlı bir şekilde Boost.MPL saldırıya uğramış şey (uyarı: Bu veeeery yüzeysel test olduğunu, bu yüzden dikkatli işlemek):

#include <boost/mpl/list.hpp> 
#include <boost/mpl/find_if.hpp> 
#include <boost/type_traits.hpp> 
#include <vector> 
#include <string> 
#include <list> 
#include <set> 

// List of candidate container types 
template<typename T> 
struct ContainersOf : boost::mpl::list< 
    std::vector<T>, 
    std::basic_string<T>, 
    std::list<T>, 
    std::set<T> 
>{}; 

// Metafunction to evaluate if IteratorT == ContainerT::iterator 
template<class IteratorT, class ContainerT> 
struct IsIteratorOf 
{ 
    typedef typename 
    boost::is_same< 
     IteratorT, 
     typename ContainerT::iterator 
    >::type type; 
}; 

// Metafunction to compute a container type from an iterator type 
template<class IteratorT> 
struct ContainerOf 
{ 
    typedef typename 
    boost::mpl::deref<typename 
     boost::mpl::find_if< 
      ContainersOf<typename std::iterator_traits<IteratorT>::value_type>, 
      IsIteratorOf<IteratorT, boost::mpl::_1> 
     >::type 
    >::type type; 
}; 

// Test 
int main() 
{ 
    ContainerOf<std::list<int>::iterator>::type l; 
    std::list<int> l2 = l; // OK 
    std::vector<int> v = l; // Fails to compile 

    return 0; 
} 
+0

Cevabınız için çok teşekkür ederiz, ancak çözümünüz konteyner tiplerine "uzmanlık" gerektirir, bkz. ContainerOf. – stepelu