2015-01-19 4 views
5

내가전달 반복자

내가 수용 할 수있는이 클래스의 생성자를 만들 T 형식의 여러 값을 유지하는 새로운 템플릿 클래스 "CrazyBucket < T>를"만들려고 해요 2 개의 순방향 반복자를 인수로 사용하여 (T 유형의) 값을 클래스 인스턴스에 복사합니다.

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

하지만와 함께

나는 다음과 같은 오류가
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

어떤 도움을 호출 할 때 어떻게해야 :

생성자

내 생성자를 정의 많이 감사합니다.

미리 감사드립니다.

+0

이 질문을 확인하십시오 - http://stackoverflow.com/questions/8751460/how-to-restrict-an-iter-to-being-a-forward-iterator –

+1

왜 이렇게 간단한 것이 아닙니다 : http : //ideone.com/EU9FTK (허용되는 경우 답변으로 게시합니다). – PaulMcKenzie

+0

@NickZavaritsky - 포인터 주셔서 감사합니다. 게시물을 올바르게 이해하지 못할 수도 있지만 포스터는 전달되는 반복자 유형을 제한하려고합니다. iterator가 가리키는 데이터 유형에 대해서는 언급하지 않습니다 (예제에서는 int). – Akanes

답변

2

A의 유형이 일치하지 않는 패션 내가 생각하면은 당신이 원하는 것과 가깝습니다.

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'; 
} 

중 하나가 제한적이며, 당신은 당신이 생각했던 최종 목표를하지 않을 수 있습니다 알고 있어야합니다 :

#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()); 
} 

또한 정적 주장 달성. 예를 들어, short의 반복은 데이터 손실없이 int으로 자연스럽게 저장되지만, SFINAE의 이러한 종류는이를 버립니다. 그것도 더 많은 확장으로 극복 될 수 있지만 그때까지는 결국 그것이 정말로 가치가 있는지를 고려해야 할 필요가 있다고 생각합니다.

어쨌든, 행운을 빈다.

+0

정말 유익하고 유익했습니다! 두 번째 코드 예제에 작은 반복자를 추가하여 이터레이터 유형도 만족되었는지 확인했습니다 (이 경우 It는 적어도 순방향 반복자입니다). – Akanes

+0

누군가가 런타임에이 작업을 수행해야하는 경우,'#include ','if (typeid std :: iterator_traits < IterType > :: value_type)! = typeid (T))'가 작업을 완료합니다. – Akanes

1

정말 생성자 여야합니까? 내가보기에 문제는 표준에 따라 불가능한 특수 생성자가 필요하다는 것입니다. 당신이 멤버 함수로 초기화를 연기 할 수하면 다음과 같은 접근 방식은 작동합니다

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()); 
} 

을 내가 생성자를 통해이 허용하는 방식으로 올 수 다른 사람이 있는지 볼 것을 고대하고있다.

편집는 : 템플릿 기반 생성자 것을 지적 세바스챤 감사 것이다 업무 단지뿐만 아니라 템플릿 방법 :

당신은 제외 SFINAE을 사용할 수 있습니다
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

생성자와 정확히 같은 코드를 사용할 수 있습니다. 단지'void init'을'CrazyContainer'로 대체하십시오. 왜 그게 효과가 없을 것이라고 생각하니? –

+0

@Sebastian, 당신 말이 맞아요. 지적 해 주셔서 고맙습니다. 나는 그것을 보여줄 답을 수정할 것입니다. –