2017-04-09 134 views
0

當我嘗試編譯我得到這個錯誤:編譯器錯誤{}匿名

In member function 'double search::IDAstar<State, MoveContainer>::dfs(const State&, double)': 153:18: error: need 'typename' before 
'MoveContainer:: const_iterator' because 'MoveContainer' is a dependent scope 153:48: error: expected ';' before 'it' 154:17: error: 'it' 
was not declared in this scope 
In member function '{anonymous}::State& {anonymous}::State::operator=(const {anonymous}::State&)': 
234:9: warning: no return statement in function returning non-void [-Wreturn-type] In instantiation of 
'double search::IDAstar<State, MoveContainer>::dfs(const State&, double) [with State = {anonymous}::State; MoveContainer = std::list<search::Move<{anonymous}::State> >]': 
122:34: required from 'std::list<State> search::IDAstar<State, MoveContainer>::solve(const State&) 
[with State = {anonymous}::State; MoveContainer = std::list<search::Move<{anonymous}::State> >]' 371:55: required from here 
152:57: error: invalid initialization of non-const reference of type 'std::list<search::Move<{anonymous}::State> >&' from an rvalue of type 
'{anonymous}::State::MoveContainer {aka std::list<search::Move<{anonymous}::State> >}' 153:66: error: dependent-name 'MoveContainer:: const_iterator' 
is parsed as a non-type, but instantiation yields a type 153:66: note: say 'typename MoveContainer:: const_iterator' if a type is meant 

search_IDAstar.h

/////////////////////////////////////////////////////////////////////////////// 
// 
// search_IDAstar.h 
// 
/////////////////////////////////////////////////////////////////////////////// 

    #ifndef SEARCH_IDASTAR_H 
    #define SEARCH_IDASTAR_H 

    #include <list> 
    #include <limits> // infinity 

namespace search 
{ 
    // A Move is a generic successor of a State (see IDAstar below). 
    template<typename State> 
    class Move 
    { 
    public: 

     // Create a move to the given successor state with the given cost. 
     Move(const State& s, double g) : 
      s(s), 
      g(g) 
     { 
      // empty 
     } 

     // Destructor 
     ~Move() 
     { 
      // empty 
     } 

     // Copy constructor 
     Move(const Move& copy) : 
      s(copy.s), 
      g(copy.g) 
     { 
      // empty 
     } 

     // Assignment operator 
     Move& operator= (const Move& rhs) 
     { 
      s = rhs.s; 
      g = rhs.g; 
     } 

     // Return successor state. 
     State state() const 
     { 
      return s; 
     } 

     // Return cost of this move. 
     double cost() const 
     { 
      return g; 
     } 

    private: 
     State s; 
     double g; 
    }; 

    // IDAstar is a generic implementation of the IDA* search algorithm. 
    // 
    // Instances of the parameter State should implement the following methods: 
    // 
    // double State::h() const; 
    // bool State::isGoal() const; 
    // MoveContainer State::successors(std::list<State>& solution) const; 
    // 
    // where h() is an admissible heuristic, isGoal() returns true iff the 
    // state is a goal state, and successors() returns a container of moves, 
    // each of which implements the following methods: 
    // 
    // State state() const; 
    // double cost() const; 
    // 
    // where state() is a successor state and cost() is the cost of the 
    // corresponding move. The successors() method may exclude cycles using 
    // the given partial solution sequence of states. 
    template<typename State, typename MoveContainer = std::list<Move<State> > > 
    class IDAstar 
    { 
    public: 

     // Constructor 
     IDAstar() : 
      solution(), 
      solved(false), 
      fLimit(0), 
      inf(std::numeric_limits<double>::infinity()) 
     { 
      // empty 
     } 

     // Destructor 
     ~IDAstar() 
     { 
      // empty 
     } 

     // Use IDA* search to find an optimal path from the given state to a 
     // goal state. Return a list of states from the given state to the 
     // goal state, or an empty list if no solution exists. 
     std::list<State> solve(const State& s) 
     { 
      solution.clear(); 
      solved = false; 
      fLimit = s.h(); 
      while (!solved && fLimit < inf) 
      { 
       fLimit = dfs(s, 0); 
      } 
      return solution; 
     } 

    private: 

     // Private unimplemented copy constructor and assignment operator 
     IDAstar(const IDAstar& copy); 
     IDAstar& operator= (const IDAstar& rhs); 

     std::list<State> solution; 
     bool solved; 
     double fLimit; 
     double inf; 

     double dfs(const State& s, double g) 
     { 
      double f = g + s.h(); 
      if (f > fLimit) 
      { 
       return f; 
      } 
      solution.push_back(s); 
      if (s.isGoal()) 
      { 
       solved = true; 
       return f; 
      } 
      double fMin = inf; 
      MoveContainer& moves = s.successors(solution); 
      for (MoveContainer::const_iterator it = moves.begin(); 
       it != moves.end(); ++it) 
      { 
       f = dfs(it->state(), g + it->cost()); 
       if (solved) 
       { 
        return f; 
       } 
       if (f < fMin) 
       { 
        fMin = f; 
       } 
      } 
      solution.pop_back(); 
      return fMin; 
     } 
    }; 
} // namespace search 

    #endif 

tiles.cpp

/////////////////////////////////////////////////////////////////////////////// 
// 
// tiles.cpp 
// 
/////////////////////////////////////////////////////////////////////////////// 

#include "search_IDAstar.h" 
#include <vector> 
#include <algorithm> // find 
#include <cstdlib> // abs 

#include <iostream> 
#include <ctime> 

namespace // unnamed namespace 
{ 
    // Number of rows/columns in the sliding tile puzzle. 
    const int rows = 4; 
    const int columns = 4; 
    const int size = rows*columns; 

    // Manhattan distance heuristic. 
    int manhattan[size][size]; 

    // A State is a configuration of a sliding tile puzzle. 
    class State 
    { 
    public: 

     // A state may be specified as a vector, where tiles[i] is the tile in 
     // the i-th position in row-major order, and the blank is specified as 
     // rows*columns == size == tiles.size(). 
     typedef std::vector<int> Tiles; 

     // Constructor 
     State(const Tiles& tiles) : 
      tiles(tiles), 
      blank(0) 
     { 
      for (int i = 0; i < size; ++i) 
      { 
       if (tiles[i] == size) 
       { 
        blank = i; 
        break; 
       } 
      } 
     } 

     // Destructor 
     ~State() 
     { 
      // empty 
     } 

     // Copy constructor 
     State(const State& copy) : 
      tiles(copy.tiles), 
      blank(copy.blank) 
     { 
      // empty 
     } 

     // Assignment operator 
     State& operator= (const State& rhs) 
     { 
      tiles = rhs.tiles; 
      blank = rhs.blank; 
     } 

     // Equality operator 
     bool operator== (const State& rhs) 
     { 
      for (int i = 0; i < size; ++i) 
      { 
       if (tiles[i] != rhs.tiles[i]) 
       { 
        return false; 
       } 
      } 
      return true; 
     } 

     // Return admissible heuristic. 
     double h() const 
     { 
      int cost = 0; 
      for (int i = 0; i < size; ++i) 
      { 
       if (i != blank) 
       { 
        cost += manhattan[i][tiles[i] - 1]; 
       } 
      } 
      return cost; 
     } 

     // Return true iff this state is a goal state. 
     bool isGoal() const 
     { 
      for (int i = 0; i < size; ++i) 
      { 
       if (tiles[i] != i + 1) 
       { 
        return false; 
       } 
      } 
      return true; 
     } 

     // Return successors of this state. 
     typedef search::Move<State> Move; 
     typedef std::list<Move> MoveContainer; 
     MoveContainer successors(std::list<State>& solution) const 
     { 
      MoveContainer moves; 

      // Move blank right. 
      if ((blank + 1)%columns != 0) 
      { 
       State s(*this); 
       s.tiles[blank] = tiles[blank + 1]; 
       s.tiles[blank + 1] = size; 
       s.blank = blank + 1; 
       if (std::find(solution.begin(), solution.end(), s) == 
        solution.end()) 
       { 
        moves.push_back(Move(s, 1)); 
       } 
      } 

      // Move blank up. 
      if (blank - columns >= 0) 
      { 
       State s(*this); 
       s.tiles[blank] = tiles[blank - columns]; 
       s.tiles[blank - columns] = size; 
       s.blank = blank - columns; 
       if (std::find(solution.begin(), solution.end(), s) == 
        solution.end()) 
       { 
        moves.push_back(Move(s, 1)); 
       } 
      } 

      // Move blank left. 
      if (blank%columns != 0) 
      { 
       State s(*this); 
       s.tiles[blank] = tiles[blank - 1]; 
       s.tiles[blank - 1] = size; 
       s.blank = blank - 1; 
       if (std::find(solution.begin(), solution.end(), s) == 
        solution.end()) 
       { 
        moves.push_back(Move(s, 1)); 
       } 
      } 

      // Move blank down. 
      if (blank + columns < size) 
      { 
       State s(*this); 
       s.tiles[blank] = tiles[blank + columns]; 
       s.tiles[blank + columns] = size; 
       s.blank = blank + columns; 
       if (std::find(solution.begin(), solution.end(), s) == 
        solution.end()) 
       { 
        moves.push_back(Move(s, 1)); 
       } 
      } 
      return moves; 
     } 

     Tiles tiles; 
     int blank; 
    }; 
} // unnamed namespace 

int main() 
{ 
    // Initialize pre-computed Manhattan distance heuristic. 
    for (int i = 0; i < size; ++i) 
    { 
     for (int j = 0; j < size; ++j) 
     { 
      manhattan[i][j] = std::abs(i/columns - j/columns) + 
       std::abs(i%columns - j%columns); 
     } 
    } 

    // Get starting puzzle configuration. 
    std::cout << "Enter puzzle: "; 
    State::Tiles tiles; 
    for (int i = 0; i < size; ++i) 
    { 
     int t; 
     std::cin >> t; 
     tiles.push_back(t); 
    } 

    // Search for a solution. 
    search::IDAstar<State> ida; 
    std::clock_t tic = std::clock(); 
    std::list<State> solution = ida.solve(State(tiles)); 
    std::clock_t toc = std::clock(); 

    // Display solution. 
    std::cout << "Solution in " << static_cast<int>(solution.size()) - 1 << 
     " moves." << std::endl; 
    for (std::list<State>::iterator it = solution.begin(); it != solution.end(); ++it) 
    { 
     State::Tiles& tiles = (*it).tiles; 
     for (size_t i = 0; i < tiles.size(); ++i) 
     { 
      std::cout << tiles[i] << " "; 
     } 
     std::cout << std::endl; 
    } 
    std::cout << "Elapsed time = " << 
     static_cast<double>(toc - tic)/CLOCKS_PER_SEC << " seconds." << 
     std::endl; 
} 

第一個錯誤MoveContainer ::爲const_iterator我輸入汽車,這是臨時修復。首先,我認爲是問題白名稱空間或iostream,但事實並非如此。我在linux下用C++ 11,C++ 14進行編譯。該程序是解決15難題的算法IDA *的例子。

回答

1
153:18: error: need 'typename' before 'MoveContainer:: const_iterator' 
because 'MoveContainer' is a dependent scope 

這個人告訴你該怎麼做。更改

for (MoveContainer::const_iterator it = moves.begin(); 

for (typename MoveContainer::const_iterator it = moves.begin(); 

Where and why do I have to put the "template" and "typename" keywords?

234:9: warning: no return statement in function returning non-void 

像它說,你State::operator=缺少return語句。

// Assignment operator 
    State& operator= (const State& rhs) 
    { 
     tiles = rhs.tiles; 
     blank = rhs.blank; 
     return *this; 
    } 

或者更好的,不要定義operator=可言,每零的規則。

52:57: error: invalid initialization of non-const reference of type 
'std::list<search::Move<{anonymous}::State> >&' from an rvalue of type 
'{anonymous}::State::MoveContainer {aka 
std::list<search::Move<{anonymous}::State> >}' 

就在這裏:

MoveContainer& moves = s.successors(solution); 

你嘗試初始化從按值返回函數的引用。刪除參考:

MoveContainer moves = s.successors(solution); 
0

在C++模板中,dependent names被假定爲值/函數,並且只有在使用typename或template關鍵字明確聲明時才能被解析爲類型名稱或模板。

在這種情況下,MoveContainer::const_iterator是依賴於模板參數MoveContainer一個名字,所以你需要告訴編譯器,這是一個類型名:

for (typename MoveContainer::const_iterator it = moves.begin(); 
    it != moves.end(); ++it) 
{ 
    //... 
} 

關於爲什麼這是必要的詳細信息,請參閱this answer

0

的錯誤信息是非常明確的:

error: need 'typename' before 
'MoveContainer:: const_iterator' because 'MoveContainer' is a dependent scope 

如果你只是更改代碼以

for (typename MoveContainer::const_iterator it = moves.begin(); 
       it != moves.end(); ++it) 

那麼它應該編譯。

原因是,對於像MoveContainer :: const_iterarator這樣的模板參數,編譯器無法判斷'const_iterator'是類型還是靜態成員。使用'typename'告訴它它是一個類型。以前的編譯器對此並不嚴格,升級到更新的編譯器時經常會遇到此錯誤。