2015-01-19 26 views
5

Bengeçirilmesi yineleyiciler

Ben kabul edebilir bu sınıf için bir kurucu oluşturmak istediğiniz tip T. birden fazla değeri tutacak olan yeni şablonu sınıf "CrazyBucket < T>" oluşturmaya çalışıyorum argümanları olarak herhangi bir 2 ileri yineleyici ve sınıf örneğine bu değerler (T tipi) kopyalayın.

CrazyBucket<T>::CrazyBucket(iterator< forward_iterator_tag, T > start, iterator< forward_iterator_tag, T > end) 
{ ... } 

Ama birlikte, ile

aşağıdaki hatayı alıyorum
vector<int> vec; 
vec.push_back(4); 
CrazyBucket<int> bucket(vec.begin(), vec.end()); 

,

candidate constructor not viable: no known conversion from 'iterator' (aka '__wrap_iter<pointer>') to 'std::iterator<std::forward_iterator_tag, int>' for 1st argument

Herhangi bir yardım aramak çalıştığınızda nasıl yapmalıdır:

Oluşturucu

Kurucum tanımlamak çok takdir edilmektedir.

Şimdiden teşekkürler.

+0

Bu sorulara bir göz atın - http://stackoverflow.com/questions/8751460/how-to-restrict-an-iterator-to-being-a-forward-iterator –

+1

Neden böyle basit bir şey değil: http: //ideone.com/EU9FTK (Kabul edilebilir ise, cevap olarak gönderirim). – PaulMcKenzie

+0

@NickZavaritsky - işaretçi için teşekkürler. Gönderiyi doğru olarak anlayamayabilirim, ancak bu poster girilen iteratör türlerini sınırlamak istiyor mu? Yineleyicinin gösterdiği veri türü hakkında konuşmaz (örneğimde, int). – Akanes

cevap

2

bir yer türlerini eşleşmeyen moda Ben düşünüyorum ne istediğine yakındır.

template<class It> 
CrazyBucket(It beg, It end) 
{ 
    static_assert(std::is_same<T, typename std::iterator_traits<It>::value_type>::value, 
     "failed to match iterator value type"); 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
} 

Ya kısıtlayıcı olduğunu ve bunu aklından geçen nihai hedef olmayabilir bilmelidir:

#include <iostream> 
#include <iterator> 
#include <vector> 

template<class T> 
class CrazyBucket 
{ 
public: 
    template<class It, typename = typename std::enable_if< 
     std::is_same< typename std::iterator_traits<It>::value_type,T>::value>::type> 
    CrazyBucket(It beg, It end) 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

int main() 
{ 
    std::vector<int> vInt; 
    CrazyBucket<int> cbOK(vInt.begin(), vInt.end()); 

    int ar[10]; 
    CrazyBucket<int> cbAlsoOK(ar, ar+10); 

    // uncomment for failure test case. 
    //std::vector<double> vDbl; 
    //CrazyBucket<int> cbFail(vDbl.begin(), vDbl.end()); 
} 

Ayrıca statik iddia ile gerçekleştirilir. Örneğin, short numaralı bir yineleme, veri kaybı olmadan doğal olarak int olarak depolanacak, ancak bu tür bir SFINAE bunu atacaktır. Bu da daha fazla genişleme ile aşılabilir, ama o zamana kadar sonunda buna değip değmeyeceğini düşünmelisiniz. Her neyse, iyi şanslar.

+0

Bu gerçekten yararlı ve bilgilendirici oldu! İkinci kod örneğine, yineleyici türünün de memnun olduğundan emin olmak için küçük bir ekleme yaptım (bu durumda, en azından bir ileri yineleyici). – Akanes

+0

Birinin bunu çalışma zamanında yapması gerekiyorsa, #include ',' if (typeid (typename std :: iterator_traits < IterType > :: value_type)! = Typeid (T)) 'işi bitirir. – Akanes

1

Gerçekten yapıcı olmak zorunda mı? Gördüğüm gibi sorun, standartlara göre mümkün olmayan özel bir kurucuya sahip olmanız gerektiğidir. Eğer üye işlevi için başlatma ertelemek durumunda aşağıdaki yaklaşım çalışır:

template<class T> 
struct CrazyContainer { 

    template<class U> 
    void init(U first,U last) { 
    for(auto it=first;it!=last;it++) { 
     // do stuff with 'it' 
    } 
    } 
}; 

main() { 
    std::vector<int> vec; 

    CrazyContainer<int> f; 
    f.init(vec.begin(),vec.end()); 
} 

Ben yapıcı üzerinden bu izin veren bir şekilde elde edebilirsiniz başkası olmadığını görmeyi dört gözle bekliyorum.

Düzenleme: templated yapıcı Buna dikkat çektiğin için Sebastian sayesinde olacak eser sadece yanısıra şablonu yöntemi:

Sen dışlamak için SFINAE kullanabilirsiniz
template<class T> 
struct CrazyContainer { 

    template<class U> 
    CrazyContainer(U first,U last) { 
    for(auto it=first;it!=last;it++) { 
     // do stuff 
    } 
    } 
}; 


main() { 
    std::vector<int> v; 
    std::set<int> s; 

    CrazyContainer<int> cv(v.begin(),v.end()); 
    CrazyContainer<int> cs(s.begin(),s.end()); 
} 
+0

Tam olarak bir kurucu ile aynı kodu kullanabilirsiniz, sadece 'void init' yerine 'CrazyContainer' ile değiştirin. Neden işe yaramayacağını düşünüyorsun? –

+0

@Sebastian, haklısınız ve işaret ettiğin için teşekkür ederim. Bunu göstermek için cevabı değiştireceğim. –

İlgili konular