在C++中声明对象和使用typedef的顺序

Mus*_*edi 3 c++ typedef predicate declaration

考虑一个类A,STL容器B和容器的二元谓词C.

容器B在类A中使用.但是类A也用在二元谓词C中.

struct C{
  bool operator()(A const &a, A const &b){
    return a.compare_variable < b.compare_variable;
  }
};
Run Code Online (Sandbox Code Playgroud)

我们需要这个谓词来定义容器,它使用它来对元素进行排序.

因为容器声明变得相当长,所以我使用typedef来简化声明.

typedef B<A, vector<A>, C> type;
Run Code Online (Sandbox Code Playgroud)

最后,我的目标是在类A中声明容器B ---其声明缩写为"type"---即,作为静态公共成员变量.

class A{
  public:
  type container1, container2;
};
Run Code Online (Sandbox Code Playgroud)

什么是正确的顺序是宣布A,B和C?

我按顺序尝试了以下变化:

  • 首先声明类A,然后是结构C,最后是typedef,我得到容器1,容器2没有命名类型的错误---类声明在类声明时不存在;

  • 首先是typedef:错误加载---类和结构都没有定义;

  • 首先使用public中的typedef声明该类:结构部分:表示第三个模板参数(C)无效的错误---尚未定义;
  • 首先声明结构:错误说该类尚未定义.

我使用的方法是不必要的麻烦,是否存在更优雅的解决方案?

T.C*_*.C. 6

重要警告:标准库容器在std::vector技术上不支持不完整类型.使用不完整类型实例化它们是未定义的行为.类型A在定义中是不完整的A,这意味着您无法可靠地使用,例如,std::vector<A>定义中的类型成员A.因此,您希望使用类似Boost容器之一的东西来保证对不完整类型的支持.

以下讨论假定Bvector支持不完整类型的实例化.如果他们不这样做,就不可能做你想做的事.


首先,找出依赖关系:

struct C {
  bool operator()(A const &a, A const &b){
    return a.compare_variable < b.compare_variable;
  }
};
Run Code Online (Sandbox Code Playgroud)

定义C自己,包括声明 C::operator(),只需要A向前宣布.但是,定义 C::operator()需要完整定义A,因为函数体引用了一个成员A.

typedef B<A, vector<A>, C> type;
Run Code Online (Sandbox Code Playgroud)

定义type仅需要A,vectorB,以及C向前声明.typedef本身不会触发模板的实例化.

class A{
public:
    type container1, container2;
};
Run Code Online (Sandbox Code Playgroud)

这会触发实例化B<A, vector<A>, C>,需要完整定义B.容器可能还需要C比较器作为完整类型,因为它们需要存储它的副本.

简而言之:

  • 定义C需要前向声明A.定义C::operator()需要完整的定义A.
  • 定义type需要前向声明A,BC.
  • 定义A需要的完整定义BC.

一旦整理了依赖项,就可以编写代码了.假设B通过包含适当的头来定义:

class A;     // Forward declare A for C's definition
struct C {
  bool operator()(A const &a, A const &b);
};

typedef B<A, vector<A>, C> type;

class A{
public:
    type container1, container2;
};

inline bool C::operator()(A const &a, A const &b){
  return a.compare_variable < b.compare_variable;
}
Run Code Online (Sandbox Code Playgroud)

请注意compare_variable,显然你需要在A中实际成为一个成员.