解析问题 - 预期的 unqualified-id - #include <array> 编译错误

Parse Issue - Expected unqualified-id - #include <array> Compile Error

我目前正在使用 objective-c++ 构建这个 ios 纸牌游戏应用。不知为何,我开始遇到 Parse 问题 - Expected unqualified-id when trying to use #include <array>。今天之前我从来没有遇到过这个问题。任何清晰度或方向将不胜感激!我已经仔细检查了我的编译器设置,以确保它知道我正在使用 C++。

Shows where the error is flagged

Compiler Settings

Compiler Settings

Shows Build time error

#ifndef Pack_hpp
#define Pack_hpp

#include "Card.hpp"
#include <array>
#include <string>
class Pack {
public:
  Pack();

private:
    //1 deck == 52 cards
    //3 decks == 156
    //6 decks == 312
  static const int PACK_SIZE = 312;
  std::array<Card, PACK_SIZE> cards;
  int next; //index of next card to be dealt
};

错误日志


In file included from /Users/MM/Documents/C++PROJECTS/C++CoreGame/Pack.cpp:9:
In file included from /Users/MM/Documents/C++PROJECTS/C++CoreGame/Pack.hpp:18:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/array:123:1: error: expected unqualified-id
_LIBCPP_BEGIN_NAMESPACE_STD
^
In file included from /Users/MM/Documents/C++PROJECTS/C++CoreGame/Pack.cpp:9:
In file included from /Users/MM/Documents/C++PROJECTS/C++CoreGame/Pack.hpp:17:
In file included from /Users/MM/Documents/C++PROJECTS/C++CoreGame/Card.hpp:13:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:503:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config:866:37: note: expanded from macro '_LIBCPP_BEGIN_NAMESPACE_STD'
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { inline namespace _LIBCPP_ABI_NAMESPACE {
                                    ^
1 error generated.

Card.cpp

#include "Card.hpp"
#include <iostream>
#include <string>

Card::Card()
    : rank(), suit() {}

//REQUIRES rank is one of "Two", "Three", "Four", "Five", "Six", "Seven",
//  "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace"
//  suit is one of "Spades", "Hearts", "Clubs", "Diamonds"
//EFFECTS Initializes Card to specified rank and suit
Card::Card(const std::string &rank_in, const std::string &suit_in)
: rank(rank_in), suit(suit_in) {}

//EFFECTS Returns the rank
std::string Card::get_rank() const
{
    return rank;
}

//EFFECTS Returns the suit.  Does not consider trump.
std::string Card::get_suit() const
{
    return suit;
}

//EFFECTS Returns true if card is a face card (Jack, Queen, King or Ace)
bool Card::is_face() const
{
    if((get_rank() == Card::RANK_JACK) || (get_rank() == Card::RANK_QUEEN) || (get_rank() == Card::RANK_KING)|| (get_rank() == Card::RANK_ACE))
    {
        return true;
    }

    else
    {
        return false;
    }
}

//EFFECTS Returns true if lhs is lower value than rhs.
//  Does not consider trump.
bool operator<(const Card &lhs, const Card &rhs)
{
    int lhs_RankWeight = 0;

    int rhs_RankWeight = 0;

    for (int i = 0; i < NUM_RANKS; i++)
    {
        if (lhs.get_rank() == RANK_NAMES_BY_WEIGHT[i])
        {
            lhs_RankWeight = i;
        }
        if (rhs.get_rank() == RANK_NAMES_BY_WEIGHT[i])
        {
            rhs_RankWeight = i;
        }
    }

        //compare left hand and right hand weights
        if (lhs_RankWeight < rhs_RankWeight)
        {
            return true;
        }
        else
        {
            return false;
        }
}

//EFFECTS Returns true if lhs is higher value than rhs.
//  Does not consider trump.
bool operator>(const Card &lhs, const Card &rhs)
{
    int lhs_RankWeight = 0;

    int rhs_RankWeight = 0;

    for (int i = 0; i < NUM_RANKS; i++)
    {
        if (lhs.get_rank() == RANK_NAMES_BY_WEIGHT[i])
        {
            lhs_RankWeight = i;
        }
        if (rhs.get_rank() == RANK_NAMES_BY_WEIGHT[i])
        {
            rhs_RankWeight = i;
        }
    }


    //compare left hand and right hand weights
    if (lhs_RankWeight > rhs_RankWeight)
    {
        return true;
    }
    else
    {
        return false;
    }
}

//EFFECTS Returns true if lhs is same card as rhs.
//  Does not consider trump.
bool operator==(const Card &lhs, const Card &rhs)
{
    if (((lhs.get_suit() == rhs.get_suit()) && (lhs.get_rank() == rhs.get_rank())))
    {
        return true;
    }
   else
   {
       return false;
    }
}

//EFFECTS Returns true if lhs is not the same card as rhs.
//  Does not consider trump.
bool operator!=(const Card &lhs, const Card &rhs)
{
    if (((lhs.get_suit() != rhs.get_suit()) || (lhs.get_rank() != rhs.get_rank())))
    {
        return true;
    }
    else
    {
        return false;
    }
}

//REQUIRES suit is a valid suit
//EFFECTS returns the next suit, which is the suit of the same color
std::string Suit_next(const std::string &suit)
{
    if(suit == Card::SUIT_SPADES)
    {
        return Card::SUIT_CLUBS;
    }
     if(suit == Card::SUIT_CLUBS)
     {
        return Card::SUIT_HEARTS;
     }
    if(suit == Card::SUIT_HEARTS)
    {
        return Card::SUIT_DIAMONDS;
    }
    if(suit == Card::SUIT_DIAMONDS)
    {
        return Card::SUIT_SPADES;
    }
    return 0;
}

//EFFECTS Prints Card to stream, for example "Two of Spades"
std::ostream & operator<<(std::ostream &os, const Card &card)
{
   return os << card.get_rank() << " of " << card.get_suit();
}

Card.hpp

#ifndef Card_hpp
#define Card_hpp

#include <iostream>
#include <string>
#include <stdio.h>


class Card
{
public:
int value;
  // rank and suit names
  static constexpr const char* const RANK_TWO = "Two";
  static constexpr const char* const RANK_THREE = "Three";
  static constexpr const char* const RANK_FOUR = "Four";
  static constexpr const char* const RANK_FIVE = "Five";
  static constexpr const char* const RANK_SIX = "Six";
  static constexpr const char* const RANK_SEVEN = "Seven";
  static constexpr const char* const RANK_EIGHT = "Eight";
  static constexpr const char* const RANK_NINE = "Nine";
  static constexpr const char* const RANK_TEN = "Ten";
  static constexpr const char* const RANK_JACK = "Jack";
  static constexpr const char* const RANK_QUEEN = "Queen";
  static constexpr const char* const RANK_KING = "King";
  static constexpr const char* const RANK_ACE = "Ace";

  static constexpr const char* const SUIT_SPADES = "Spades";
  static constexpr const char* const SUIT_HEARTS = "Hearts";
  static constexpr const char* const SUIT_CLUBS = "Clubs";
  static constexpr const char* const SUIT_DIAMONDS = "Diamonds";

  //EFFECTS Initializes Card to empty hand
  Card();

  //REQUIRES rank is one of "Two", "Three", "Four", "Five", "Six", "Seven",
  //  "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace"
  //  suit is one of "Spades", "Hearts", "Clubs", "Diamonds"
  //EFFECTS Initializes Card to specified rank and suit
  Card(const std::string &rank_in, const std::string &suit_in);

  //EFFECTS Returns the rank
  std::string get_rank() const;

  //EFFECTS Returns the suit.
  std::string get_suit() const;

  //EFFECTS Returns true if card is a face card (Jack, Queen, King or Ace)
  bool is_face() const;

private:
    std::string rank;
    std::string suit;
};

// Suits in order from lowest suit to highest suit.
constexpr const char* const SUIT_NAMES_BY_WEIGHT[] = {
  Card::SUIT_SPADES,
  Card::SUIT_HEARTS,
  Card::SUIT_CLUBS,
  Card::SUIT_DIAMONDS
};
const int NUM_SUITS = 4;

// Ranks in order from lowest rank to highest rank.
constexpr const char* const RANK_NAMES_BY_WEIGHT[] = {
  Card::RANK_TWO,
  Card::RANK_THREE,
  Card::RANK_FOUR,
  Card::RANK_FIVE,
  Card::RANK_SIX,
  Card::RANK_SEVEN,
  Card::RANK_EIGHT,
  Card::RANK_NINE,
  Card::RANK_TEN,
  Card::RANK_JACK,
  Card::RANK_QUEEN,
  Card::RANK_KING,
  Card::RANK_ACE
};
const int NUM_RANKS = 13;

//EFFECTS Returns true if lhs is lower value than rhs.
//  Does not consider trump.
bool operator<(const Card &lhs, const Card &rhs);

//EFFECTS Returns true if lhs is higher value than rhs.
//  Does not consider trump.
bool operator>(const Card &lhs, const Card &rhs);

//EFFECTS Returns true if lhs is same card as rhs.
//  Does not consider trump.
bool operator==(const Card &lhs, const Card &rhs);

//EFFECTS Returns true if lhs is not the same card as rhs.
//  Does not consider trump.
bool operator!=(const Card &lhs, const Card &rhs);

//REQUIRES suit is a valid suit
//EFFECTS returns the next suit, which is the suit of the same color
std::string Suit_next(const std::string &suit);

//EFFECTS Prints Card to stream, for example "Two of Spades"
std::ostream & operator<<(std::ostream &os, const Card &card);

#endif
*

注意:问题自最初发布以来已经发生了很大变化。这是最终答案,但我会保留我之前写的内容。

问题是单独的星号 (*) 似乎偷偷溜进了您的 Card.hpp 文件的末尾。

错误出现在 <array> 中的原因是因为 #include 只是执行文本替换,并且因为 <array> 紧接在 Card.hpp 之后包含在 [=18] 中=]:

#include "Card.hpp"
#include <array>

星号可能不是问题,这取决于它后面的内容,但是里面的代码<array>当然不会指望跟随一个流氓*,因此编译错误。


上一个答案 - 为后代保留 - 这是为了回应仅包含 Pack.hpp 的问题而发布的。按照下面的评论了解我们最终是如何得到答案的。

包括守卫

#ifndef Pack_hpp
#define Pack_hpp

表明此代码来自名为 Pack.hpp 的文件,即头文件。

我怀疑它是直接或间接从 .m(纯 Objective-C)文件中包含的,并且 Objective-C 编译器无法理解此 C++ 代码。 (在这种情况下,Transitivity 表示它被另一个头文件包含,而另一个头文件被 .m 文件包含,或者它被另一个头文件包含的头文件包含,等等。最终形成一个链导致头文件直接包含在 .m 文件中。)

请确保您仅 #include 此文件来自 .cpp.mm 个文件。

注意clang在打印错误的时候实际上会告诉你#include链,你只需要跟着它回到编译单元的文件来识别问题。

模仿@pmdj 的回答,我遇到了同样的问题——这次在 AVAnimation 中弹出构建错误(我正在导入 AVFoundation)。

我的答案是我忘记添加一个字符——C++}结束后的;class 完全在不同的文件中:

class SubclassSomething : public Something {

};   // <-----

直到我注释掉导致构建错误的 AVFoundation 导入行,Xcode 才真正告诉我是什么原因造成的。