编译错误{匿名}

时间:2017-04-09 14:44:01

标签: c++ compiler-errors c++14

当我尝试编译时,我得到了这个错误:

 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我输入auto,那是临时修复。首先我认为问题是whit命名空间或iostream,但事实并非如此。我用linux中的c ++ 11,c ++ 14编译。程序是算法IDA *的例子,用于解决15个难题。

3 个答案:

答案 0 :(得分: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=缺少一个返回声明。

    // 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);

答案 1 :(得分:0)

在c ++模板中,dependent names被假定为值/函数,并且只有在使用typename或template关键字明确声明它时才能将其解析为类型名称或模板。

在这种情况下,MoveContainer::const_iterator是一个取决于模板参数MoveContainer的名称,因此您需要告诉编译器它是一个类型名称:

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

有关为何需要这些内容的详细信息,请参阅this answer

答案 2 :(得分: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'告诉它它是一个类型。较旧的编译器对此并不严格,并且在升级到更新的编译器时经常会出现此错误。