考虑一个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;
}
};
我们需要这个谓词来定义容器,它使用它来对元素进行排序。
因为容器声明变得相当长,所以我使用typedef来简化声明。
typedef B<A, vector<A>, C> type;
最后,我的目标是在类A中声明容器B ---其声明缩写为“type”---即,作为静态公共成员变量。
class A{
public:
type container1, container2;
};
什么是正确的顺序是声明A,B和C?
我按顺序尝试了以下变化:
首先声明类A,然后是结构C,最后是typedef,我得到容器1,容器2没有命名类型的错误---类声明在类声明时不存在;
首先是typedef:错误加载---类和结构都没有定义;
我使用的方法是不必要的麻烦,是否存在更优雅的解决方案?
答案 0 :(得分:6)
重要警告:标准库容器,例如std::vector
技术上do not support incomplete types。使用不完整类型实例化它们是未定义的行为。类型A
在A
的定义中不完整,这意味着您无法在{{1}的定义中可靠地使用类型std::vector<A>
的成员}}。因此,您希望使用one of Boost's containers之类的内容来保证对不完整类型的支持。
以下讨论假设A
和B
支持不完整类型的实例化。如果他们不这样做,就不可能做你正在尝试的事情要做。
首先,找出依赖关系:
vector
定义struct C {
bool operator()(A const &a, A const &b){
return a.compare_variable < b.compare_variable;
}
};
本身,包括声明 C
,只需要C::operator()
进行前向声明。但是,定义 A
需要C::operator()
的完整定义,因为函数体引用了A
的成员。
A
定义typedef B<A, vector<A>, C> type;
只需要type
,A
,vector
和B
进行前向声明。 typedef本身并不触发模板的实例化。
C
这会触发class A{
public:
type container1, container2;
};
的实例化,需要B<A, vector<A>, C>
的完整定义。容器可能还需要比较器B
为完整类型,因为它们需要存储它的副本。
简而言之:
C
需要C
的前瞻声明。定义A
需要C::operator()
的完整定义。A
需要type
,A
和B
的前瞻声明。C
需要A
和B
的完整定义。一旦您整理了依赖项,就可以编写代码。假设通过包含适当的标头来定义C
:
B
请注意,您需要在A中实际成为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;
}
成员。
答案 1 :(得分:1)
所以你想要这样的东西?
class A {
struct C{
bool operator()(A const &, A const &);
};
typedef B<A, vector<A>, C> type;
type c1, c2;
public:
int compare_variable; // ?
};
// the definition below should either go in a .cpp file,
// or you should mark it inline
bool A::C::operator()(A const &x, A const &y) {
return x.compare_variable < y.compare_variable;
}