2013-02-12 2 views
1

저는 스택으로 사용하는 deque를 가진 클래스를 가지고 있습니다 (그냥 deque를 선택했을 때 벡터가 될 수 있습니다).컨테이너를 포장하는 역전 된 어댑터를 어떻게 반환 할 수 있습니까?

필자는 소비자가 스택의 내용 (std :: stack에서 수행 할 수없는 것)을 반복 할 수 있기를 바랍니다. 나는 현재 push_back()을 사용하여 스택에 항목을 푸시합니다. 따라서 순방향 순서로 내용을 반복하는 경우 맨 아래에서 맨 위로 이동합니다.

역순으로 항목을 노출하여 for (auto e : thestack)를 사용하여 스택을 반복하는 것이 하향식으로 작동하도록하는 것이 좋습니다.

새로운 for 루프 구문 (범위 기반 알고리즘은 물론)에 대한 반복 순서를 뒤집을 수있는 몇 가지 해결책을 보여주는 C++11 reverse range-based for-loop이 있습니다.

내게 명확하지 않은 점은 내 사용자가 자동으로 뒤집힌 양키 (deque)에 액세스 할 수있게 해주는 간단한 방법을 제공하는 방법입니다.

const std::deque<T> & GetStack() const { return m_stack; } 

소비자가 반전에 대한 책임 수 : 실제 노력없이, 단순히 기본 양단 큐에 const를 & 액세스를 허용 할 수 있습니다 여기에

for (auto e : reverse(m_toolstack.GetStack())) 

, 나는 다음과 같은 솔루션을 사용하려고 시도하고있다 모든 컴파일 위의

template<class Fwd> 
struct reverser_generic 
{ 
    Fwd &fwd; 
    reverser_generic(Fwd& fwd_): fwd(fwd_) {} 
    typedef std::reverse_iterator<typename Fwd::iterator> reverse_iterator; 
    reverse_iterator begin() { return reverse_iterator(std::end(fwd)); } 
    reverse_iterator end() { return reverse_iterator(std::begin(fwd)); } 
}; 

template<class Fwd> 
struct reverser_special 
{ 
    Fwd &fwd; 
    reverser_special(Fwd& fwd) : fwd(fwd) { } 
    auto begin() -> decltype(fwd.rbegin()) { return fwd.rbegin(); } 
    auto end() -> decltype(fwd.rend()) { return fwd.rend(); } 
}; 

template<class Fwd> 
auto reverse_impl(Fwd& fwd, long) -> decltype(reverser_generic<Fwd>(fwd)) 
{ 
    return reverser_generic<Fwd>(fwd); 
} 

template<class Fwd> 
auto reverse_impl(Fwd& fwd, int) -> decltype(fwd.rbegin(), reverser_special<Fwd>(fwd)) 
{ 
    return reverser_special<Fwd>(fwd); 
} 

template<class Fwd> 
auto reverse(Fwd&& fwd) -> decltype(reverse_impl(fwd,int(0))) 
{ 
    static_assert(!(std::is_rvalue_reference<Fwd&&>::value), "Cannot pass an rvalue reference to reverse()"); 
    return reverse_impl(fwd,int(0)); 
} 

제대로 (자이브 Dadson 등 덕분에이 솔루션을..) VS2012를 사용하여 실행 : 반대합니다. ,

auto GetContents() const -> decltype(reverse(m_stack)) { return reverse(m_stack); } 

위의 오류 :

는하지만, 내 스택 외관에, 정말 단순히 항상 기본 컨테이너의 역을 반환하려면,하지만 난 재치있는 방식으로이 작업을 수행하는 방법에 대한 불분명 해요 m_stack은 알 수 없음을 나타냅니다. this-> m_stack도 똑같이 알 수 없습니다.

"회원 m_stack의 반대편이 무엇이든간에"반환하는 방법은 무엇입니까? 이 답변하면

주, 나 또한 어떻게 역 (m_stack)의 decltype 무엇이든의 CONST &을 반환 할 "필요?

+1

'decltype (reverse (std :: declval ())) ' – Xeo

+0

대신 클래스에 맞는 반복자를 만들지 않겠습니까? –

+0

네, 저 역시 저에게 일어났습니다. 게으름과 내가이 길을 걸어 왔음을 알게 된 어떤 완고함. :) – Mordachai

답변

1

m_stack?

의 선언 전에 GetContents의 선언이다

struct X 
{ 
    auto f() -> decltype(m_x) { return m_x; } // ERROR 
    int m_x; 
    auto g() -> decltype(m_x) { return m_x; } // OK 
}; 
: 그들은 아직 선언되지 않은 클래스 멤버를 참조 할 수 없습니다 즉 늦은 지정된 반환 형식에

이름은 함수 서명의 나머지 부분에 이름과 동일한 규칙을 준수해야

는 그것이 작동되도록, 하나 또는 당신이 그것을 참조하기 전에 m_stack가 선언 된 보증 (당신이 std::vectorstd::deque에서 m_stack의 유형을 변경 한 경우에는 GetContents의 서명을 업데이트해야합니다 의미) 유형을 참조 std::declval를 사용하십시오.

+0

오! 나는 이것이 잘 될지 몰랐다. 이것이 여기에 요구된다는 것을 좌절시키지 만, 일단 당신이 알게되면 ... 나는 괜찮다고 생각합니다. – Mordachai

+1

N.B. 늦은 특정 반환 형식은 함수 매개 변수를 참조하는 데 유용하지만 그렇게하지는 않으므로 쉽게 'decltype (m_stack) GetContents() const'라고 쓸 수 있습니다 ... 그러면 조금 더있을 수 있습니다 'stack_type GetContents() const; '를 쓰려고 시도한 것처럼'm_stack'이 범위 내에 있어야한다는 것을 이해할 수 있습니다. 아직 선언되지 않은 typedef를 참조합니다. –

관련 문제