C++ 无法向前声明C typedef结构-正在寻找其他建议

C++ 无法向前声明C typedef结构-正在寻找其他建议,c++,c++17,C++,C++17,我使用的是第三方C库(),它的头中定义了宏和struct,如下所示: // raylib.h #define RED { 230, 41, 55, 255 } // Red // Color type, RGBA (32bit) typedef struct Color { unsigned char r; unsigned char g; unsigned char b; unsigned char a; } Color; 我想把它封装在我自己的C++头文件和名为e

我使用的是第三方C库(),它的头中定义了宏和
struct
,如下所示:

// raylib.h
#define RED { 230, 41, 55, 255 }     // Red

// Color type, RGBA (32bit)
typedef struct Color {
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
} Color;
我想把它封装在我自己的
C++
头文件和名为
engine.h
engine.cc
的源文件中,它们只公开相关的函数和宏

为了确保只有
engine.cc
可以访问标题
raylib.h
,我希望:

  • engine.h
    中向前声明
    struct Color
    ,并
  • #仅在
    engine.cc
  • 类似这样的内容():

    不幸的是,这不起作用,因为我不能转发声明typedef,因为它也在typedef中定义了结构

    我的问题是,如果我想对包含
    engine.h
    的所有其他文件隐藏
    raylib.h
    ,最好的选择是什么


    我尝试过的一种有效方法是拥有自己的
    enum类
    ,这些颜色由
    engine.cc
    中匿名命名空间中的帮助函数解析。helper函数使用
    开关
    语句解析它。但这是乏味的,因为我需要为我想要使用的每种新颜色编写大量代码。而且,
    Color
    只是具有关联宏的结构之一。还有很多,我不想为它们中的每一个创建这些帮助函数。

    我解决了这个问题,但在一个命名空间中定义了我自己的
    结构颜色
    ,该命名空间与
    raylib.h
    中的命名空间相同,并在
    engine.cc
    中创建了一个将一个转换为另一个的帮助函数

    // engine.h
    
    namespace Engine {
    namespace Colors {
    struct Color {
      unsigned char r;
      unsigned char g;
      unsigned char b;
      unsigned char a;
    };
    
    extern const Color Red;
    extern const Color Green;
    extern const Color Blue;
    extern const Color Black;
    
    }  // namespace Colors
    
    void SetBackgroundColor(const Colors::Color);
    }  // namespace Engine
    
    
    
    
    // engine.cc
    
    namespace Engine {
    using RayColor = ::Color;
    namespace Colors {
    const Color Red = RED;
    const Color Green = GREEN;
    const Color Blue = BLUE;
    const Color Black = BLACK;
    
    namespace {
    RayColor GetRayColor(const Color color) {
      return RayColor{color.r, color.g, color.b, color.a};
    }
    }  // namespace
    }  // namespace Colors
    
    void SetBackgroundColor(const Colors::Color color) {
      ::ClearBackground(Colors::GetRayColor(color));
    }
    }  // namespace Engine
    
    这是因为我可以轻松地从
    Engine::Colors::Color
    转换为
    Color
    。另外,因为所有颜色宏都只是大括号中的数字,所以我可以轻松地使用它们来指定给我自己的结构

    当然,此解决方案特定于
    raylib.h
    和我的需求。我希望这个问题有一个更普遍的解决办法


    我不确定这种方法对性能的影响有多大,但我现在会尝试一下,如果有任何问题,我会重新访问。

    为什么
    typedef Color
    ?您的代码为我编译:,请显示@AlanBirtles-谢谢。它可以编译,但是
    engine.h
    中的
    Color
    engine.cc
    中的
    Color
    不同。当你尝试使用
    SetBackgroundColor(Engine::Colors::Red)
    时,它会说
    不能从颜色转换到颜色
    @AlanBirtles-关于
    typedef Color
    ,对不起,我的意思是写
    typedef struct Color
    。关于
    struct
    s(和
    union
    s和
    enum
    s),C和C++之间有一个区别:在C中,
    struct Color
    只能用作
    struct Color
    。因此,
    typedef结构颜色{}Color为方便起见。在C++中,结构颜色> /COD>可以用作<代码>颜色< /代码>。
    struct
    的标识符成为类型的名称-更方便(IMHO)。所以,在C++中不需要像C那样的<<代码> TyPulf
    S。IMO这是过于复杂的问题,只是为以后的人(包括你自己)创建未来的头痛,试图读取代码,并想知道为什么F会这样做。this@M.M-我同意你的看法。我希望我不必这么做。但现在,这是我能想到的最好的选择。除了必须在标题
    engine.h
    中包含
    raylib.h
    之外,我对其他选择持开放态度。我希望有一个更通用的解决方案来解决这个问题。C++20将引入模块,我希望这将是一个更通用的解决方案。@Eljay-我看过模块,不确定它们在这种情况下是否有用。解决这个问题的唯一方法是,我可以在没有完整定义的情况下(而不仅仅是指针或对前向声明类型的引用)前向声明类型和变量。
    // engine.h
    
    namespace Engine {
    namespace Colors {
    struct Color {
      unsigned char r;
      unsigned char g;
      unsigned char b;
      unsigned char a;
    };
    
    extern const Color Red;
    extern const Color Green;
    extern const Color Blue;
    extern const Color Black;
    
    }  // namespace Colors
    
    void SetBackgroundColor(const Colors::Color);
    }  // namespace Engine
    
    
    
    
    // engine.cc
    
    namespace Engine {
    using RayColor = ::Color;
    namespace Colors {
    const Color Red = RED;
    const Color Green = GREEN;
    const Color Blue = BLUE;
    const Color Black = BLACK;
    
    namespace {
    RayColor GetRayColor(const Color color) {
      return RayColor{color.r, color.g, color.b, color.a};
    }
    }  // namespace
    }  // namespace Colors
    
    void SetBackgroundColor(const Colors::Color color) {
      ::ClearBackground(Colors::GetRayColor(color));
    }
    }  // namespace Engine