0

When I try compile I get this errors:

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

First error MoveContainer:: const_iterator i type auto and that was temporary fix. First i think is problem whit namespace or iostream, but it's not. I compile with c++11, c++14 in linux. The progam is example of algorithm IDA* for solving 15 puzzle.

kennytm
  • 469,458
  • 94
  • 1,022
  • 977
Pera
  • 3
  • 4

3 Answers3

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

This one tells you what to do. Change

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

to

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

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

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

Like it says, your State::operator= is missing a return statement.

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

Or better, don't define operator= at all, per the Rule of Zero.

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

Right here:

MoveContainer& moves = s.successors(solution);

you try to initialize a reference from a function that returns by value. Drop the reference:

MoveContainer moves = s.successors(solution);
Community
  • 1
  • 1
aschepler
  • 65,919
  • 8
  • 93
  • 144
0

In c++ templates, dependent names are assumed to be values/functions, and can only be parsed as a typename or template if you explicitly state it using the typename or template keywords.

In this case, MoveContainer::const_iterator is a name which depends on the template parameter MoveContainer, so you need to tell the compiler that it is a typename:

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

For more info on why this is necessary, see this answer.

Community
  • 1
  • 1
Joseph Ireland
  • 2,220
  • 8
  • 19
0

The error message is fairly explicit:

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

If you just change the code to

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

then it should compile.

The reason is that for template arguments like MoveContainer::const_iterarator, the compiler can't tell if 'const_iterator' is a type or a static member. Using 'typename' tells it that it is a type. Older compilers weren't strict about this, and you often get this error when upgrading to a more recent compiler.

Paul Floyd
  • 3,765
  • 5
  • 25
  • 37