2015-01-22 12 views
2

포인터를 사용하지 않는 포인터를 사용한 경로 찾기 알고리즘의 일부를 리펙토링하려고합니다. 불행히도 나는 그 참조에 대해 knowledgable 아니에요. 오류가 발생합니다. Invalid operands to binary expression ('std::__1::reference_wrapper<Tile>' and 'const std::__1::reference_wrapper<Tile>')reference_wrapper 벡터를 사용하는 방법

나는 또한 그 의미가 무엇인지 모릅니다. 내 코드는 아래에 있으며, 그 줄에서 오는 것을 수집 할 수 있습니다 : openList.erase(std::find(openList.begin(), openList.end(), current)); 그러나이 문제를 해결하는 방법을 잘 모르겠습니다.

bool TileMap::tilesBetween(Tile& p_start, Tile& p_end) 
{ 
    std::vector<std::reference_wrapper<Tile>> openList; 
    std::vector<std::reference_wrapper<Tile>> closedList; 

    openList.push_back(p_start); 

    do 
    { 
     std::sort(openList.begin(), openList.end(), sortF()); 
     Tile& current = openList[0]; 
     closedList.push_back(current); 
     openList.erase(std::find(openList.begin(), openList.end(), current)); 
     if(std::find(closedList.begin(), closedList.end(), p_end) != closedList.end()) 
     { 
      return true; 
     } 

     std::vector<std::reference_wrapper<Tile>> adjacentTiles; 
     if (current.m_coordinates.x > 0) 
     { 
      adjacentTiles.push_back(m_tiles[current.m_coordinates.y * m_width + (current.m_coordinates.x - 1)]); 
     } 
     if (current.m_coordinates.x < m_width) 
     { 
      adjacentTiles.push_back(m_tiles[current.m_coordinates.y * m_width + (current.m_coordinates.x + 1)]); 
     } 
     if (current.m_coordinates.y > 0) 
     { 
      adjacentTiles.push_back(m_tiles[(current.m_coordinates.y - 1) * m_width + current.m_coordinates.x]); 
     } 
     if (current.m_coordinates.y < m_height) 
     { 
      adjacentTiles.push_back(m_tiles[(current.m_coordinates.y + 1) * m_width + current.m_coordinates.x]); 
     } 

     for(auto t : adjacentTiles) 
     { 
      if(std::find(closedList.begin(), closedList.end(), t) != closedList.end()) 
      { 
       continue; 
      } 

      if(std::find(openList.begin(), openList.end(), t) == closedList.end()) 
      { 
       openList.push_back(t); 
      } 
     } 
    } 
    while(!openList.empty()); 

    return false; 
} 

편집 : sortF

struct sortF 
{ 
    bool operator()(const Tile* p_a, const Tile* p_b) const 
    { 
     return p_a->f < p_b->f; 
    } 
}; 

업데이트를 게시 : 제안에 따라, 나는 대신 참조 포인터를 사용하는 기능을 변경했습니다. 그것은 작동하는 것으로 보이지만 그것이 끝나기 전에 더 구현해야합니다.

bool TileMap::tilesBetween(Tile* p_start, Tile* p_end) 
{ 
    std::vector<Tile*> openList; 
    std::vector<Tile*> closedList; 

    std::cout << p_start << ", "; 

    openList.push_back(p_start); 

    do 
    { 
     std::sort(openList.begin(), openList.end(), sortF()); 
     Tile* current = openList[0]; 
     closedList.push_back(current); 
     openList.erase(std::find(openList.begin(), openList.end(), current)); 
     if(std::find(closedList.begin(), closedList.end(), p_end) != closedList.end()) 
     { 
      return true; 
     } 

     std::vector<Tile*> adjacentTiles; 
     if (current->m_coordinates.x > 0) 
     { 
      adjacentTiles.push_back(&m_tiles[current->m_coordinates.y * m_width + (current->m_coordinates.x - 1)]); 
     } 
     if (current->m_coordinates.x < m_width) 
     { 
      std::cout << &m_tiles[current->m_coordinates.y * m_width + (current->m_coordinates.x + 1)] << std::endl; 
      adjacentTiles.push_back(&m_tiles[current->m_coordinates.y * m_width + (current->m_coordinates.x + 1)]); 
     } 
     if (current->m_coordinates.y > 0) 
     { 
      adjacentTiles.push_back(&m_tiles[(current->m_coordinates.y - 1) * m_width + current->m_coordinates.x]); 
     } 
     if (current->m_coordinates.y < m_height) 
     { 
      adjacentTiles.push_back(&m_tiles[(current->m_coordinates.y + 1) * m_width + current->m_coordinates.x]); 
     } 

     for(auto t : adjacentTiles) 
     { 
      if(std::find(closedList.begin(), closedList.end(), t) != closedList.end()) 
      { 
       continue; 
      } 

      if(std::find(openList.begin(), openList.end(), t) == openList.end()) 
      { 
       openList.push_back(t); 
      } 
     } 
    } 
    while(!openList.empty()); 

    return false; 
} 
+0

무엇 라인 오류가에서 오는가 보여주기 위해? – Barry

+0

@ 배리 - 나는'openList.erase (std :: find (openList.begin(), openList.end(), current));'줄로 좁혔다 고 생각한다. –

+0

'Tile'에'operator =='가 구현되어 있습니까? – Barry

답변

0

귀하의 문제는 여기에 있습니다 :

std::sort(openList.begin(), openList.end(), sortF()); 

귀하의 sortF 잘못된 비교 대상이다. operator()는 다음과 같이해야합니다

bool operator()(const Tile& lhs, const Tile& rhs) const 
//    ^^^ ref ^^^  ^^^ ref ^^^ 
{ 
    return lhs.f < rhs.f; 
} 

대신에 :

bool operator()(const Tile* p_a, const Tile* p_b) const 
//    ^^^ ptr ^^^  ^^^ ptr ^^^ 

당신은 reference_wrapper<Tile>의 벡터, Tile* 아닌 벡터를 가지고있다.

+0

죄송합니다. 게시하지 않았을 때 전체 기능을 업데이트했습니다. 당신이 그것을 사용했을 때 당신이 제안한 방식대로했습니다. –

2

I can gather that it comes from the line: openList.erase(std::find(openList.begin(), openList.end(), current)); but I'm not sure how to fix this.

std::findstd::reference_wrapper<Tile>을 반복하지 Tile& 자체. 따라서

Tile& current = openList[0]; 
    openList.erase(std::find(openList.begin(), openList.end(), current)); 

올바르지 않습니다. 이것을

openList.erase(std::find_if(openList.begin(), openList.end(), [&](const std::reference_wrapper<Tile> &i) 
    { 
     return i.get() == current; 
    })); 

std::reference_wrapper::get으로 변경하십시오.

A는 간단 working example는이

#include <algorithm> 
#include <list> 
#include <vector> 
#include <iostream> 
#include <functional> 

struct S 
{ 
    int val; 
    S(int i) : val(i) {} 
}; 

int main() 
{ 
    std::list<S> l = {-4, -3, -2, -1, 0, 1, 2, 3, 4}; 
    std::vector<std::reference_wrapper<S>> v(l.begin(), l.end()); 

    auto& x = l.front(); 
    v.erase(std::find_if(v.cbegin(), v.cend(), [&](const std::reference_wrapper<S> &i) 
    { 
     return i.get().val == x.val; 
    })); 
    std::cout << v[0].get().val; 
} 
+1

작동하지만 수동으로 'reference_wrapper'를 래핑 해제하는 것은 암시 적 변환 연산자가'T &'로되어 있기 때문에 필요하지 않습니다. 그래서 당신은 람다를 피할 수 있고'S'가 동등한 비교가 가능한 한'find'를 사용할 수 있습니다 - http://coliru.stacked-crooked.com/a/4dcd9b9164a93645 – Praetorian

+0

수동 언 래핑없이 시도했습니다 - 람다 - 헛되이,하지만 'operator =='을 멤버 함수로 구현했는데, 외부 친구 함수로 변경했을 때 작동했습니다! 당신 덕분에 나는'std'의 일반 알고리즘으로 만든 _ [대칭 가정] (http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=523)에 대해 배웠습니다. – legends2k