选择备用实现和转发声明

时间:2015-04-13 18:23:45

标签: c++ forward-declaration clang++

我有一个库,它有一个由下游客户端代码使用的特定类。该类派生自一组基类。如,

A.h :-
namespace my_lib {
  class A : public BaseClass1 {
  };
}

现在,我想提供一个A类的替代实现,它从另一组基类派生,并允许客户端选择要编译/链接的基类。因此,我想要一些方法在同一个共享/静态库中释放这两个实现。

如,

NewA.h :-
namespace my_lib {
  class newA : public BaseClass2 {
  };
}

我尝试使用typedef,但这会导致前向声明出现问题。如,

ClientA.h :-
namespace my_lib {
  #ifdef LEGACY_A
    typedef A ClientA;
  #else
    typedef NewA ClientA;
  #endif
}

因此,客户端只使用类名my_lib :: ClientA。但是,如果客户端具有前向声明,则会导致下游问题。

如,

clientclass.h :-
namespace my_lib {
  class ClientA;
  class clientClass {
    clientClass(ClientA* a);
  };
}

这会出错: -

clientclass.h: error: definition of type 'ClientA' conflicts with typedef of the same name
class ClientA;
      ^
ClientA.h: note: 'ClientA' declared here
typedef my_lib::newA ClientA;

另一方面,如果我使用命名空间和using指令,我又会遇到麻烦: -

A.h:-
namespace my_lib_legacy {
  class A : public BaseClass1 {
  };
}
newA.h :-
namespace my_lib_new {
  class A : public BaseClass2 {
  };
}
ClientA.h :-
namespace my_lib {
  #ifdef LEGACY_A
    using my_lib_legacy::A;
  #else
    using my_lib_new::A;
  #endif
}
clientclass.h :-
namespace my_lib {
  class A;
  class clientClass {
    clientClass(A* a);
  };
}

但是,这会引发歧义错误,如下所示: -

clientclass.h: error: reference to 'A' is ambiguous
  explicit clientClass(A* a)
                       ^
clientclass.h: note: candidate found by name lookup is 'my_lib::A'
class A;
      ^
ClientA.h: note: candidate found by name lookup is 'my_lib::A'
using my_lib_legacy::A;

2 个答案:

答案 0 :(得分:1)

我只是告诉您的客户,他们不能转发声明您的库组件并使用typedef方法。这对我来说似乎完全合情合理。

由于您的图书馆不会一直在改变,并且它已经在内部处理任何依赖于相关的前向声明,因此他们没有理由需要通过从您的库中向前声明来依赖特定的内部实现。

如果您愿意,您也可以选择提供<your_lib_name_fwd>标题,该标题适当地向前宣布关键组件,但我不认为这是强制性的。这是先例,例如标准库<iosfwd>

答案 1 :(得分:0)

如果我了解您的问题,您可以使用

ClientA.h :-
#include "A.h"
#include "NewA.h"
namespace my_lib {
  #ifdef LEGACY_A
    typedef A ClientA;
  #else
    typedef NewA ClientA;
  #endif
}
clientclass.h :-
#include "ClientA.h"
namespace my_lib {
  // you already define ClientA with typedef
  class clientClass {
    clientClass(ClientA* a);
  };
}

ClientA.h :-
namespace my_lib {
  #ifdef LEGACY_A
    #define ClientA A
  #else
    #define ClientA newA
  #endif
}
clientclass.h :-
#include "A.h"
#include "NewA.h"
#include "ClientA.h"
namespace my_lib {
  class ClientA;
  class clientClass {
    clientClass(ClientA* a);
  };
}