在SWIG中处理来自self的专用实例的类继承

时间:2014-04-10 22:42:35

标签: c++ inheritance c++11 swig template-specialization

我有一些代码可以在C ++中编译和工作(只要我转发声明通用模板类,然后是专用实例,然后定义通用模板类 - 请参阅inheriting from class of specialized self?)。但是,当我尝试使用SWIG将C#绑定添加到类时,它会导致SWIG崩溃或者不包含继承类中的方法。我相信这只能在C ++ 11中实现,但我不确定,因为我没有用旧的编译器尝试过这个。

这是一个玩具示例:

template <typename T, int N = 0> class A;

template <typename T> class A<T, 0>
{
public:
    A() : mFoo(NULL)    {}
    virtual ~A()        {}

    T* getFoo() { return mFoo; }

protected:
    T* mFoo;
};

template <typename T, int N = 0> class A : public A<T, 0>
{
public:
    A() : A<T, 0>(), mBar(N)    {}
    virtual ~A()                {}

    int getBar() const { return mBar; }

protected:
    int mBar;
};

在程序中,我可以实例化A<char,10>的实例(例如),并且可以访问mFoo和mBar,或者只是实例化A的实例并且只能访问mFoo。我也可以使用像

这样的参数的方法
void baz(A<T, 0>* anyA)

,该方法将接受A<T, 0>A<T, n>个实例。

对于上下文和解释,此模式适用于可以是动态或固定大小的容器。如果它们是动态的,您可以将它实例化为A<T, 0>并且没有继承的开销等,或者您可以拥有一个固定大小的容器(A<T, N>,其中N> 0)使用继承,但可以访问所有“基”类方法,可以根据需要覆盖它们,并且仍然可以接受作为接受容器的动态或固定大小实例的方法的参数。

但是,当我尝试使用SWIG以便我可以在其他语言中使用此类时,我遇到了问题。

起初,我尝试过类似的事情:

%template(tA) A<char, 0>;

但这会导致SWIG崩溃(至少在我目前使用的3.0.0版本中)。

接下来,我认为,与SWIG中的所有模板继承一样,我需要为基类和继承者类创建一个现有模板(如果两者都是模板化的)。所以我试过

%template(tABase) A<char, 0>;
%template(tA) A<char>;

这也会导致SWIG崩溃。

所以,我试图变得有点聪明,并利用SWIGS的能力为继承的类使用“无名”模板,并做了类似的事情:

%template() A<char, 0>;
%template(tA) A<char>;

这可以避免崩溃,我得到了tA类的输出,但它只有继承类A<T, N>中的方法等,并且实际上并不从A<char, 0>专用模板实例继承它需要,因此我无法访问A<char, 0>的“基础”类中的所有方法和数据。

有没有其他人试图让SWIG来处理这个问题?成功?是否有一个命令行参数,我可以传递给SWIG,使事情有效(并阻止它崩溃)?

1 个答案:

答案 0 :(得分:1)

我能看到解决问题的最简单方法就是停止如此幻想,以至于混淆了其他语言,在C ++中扮演 的优势:

template<typename T>
struct A0_impl;
template<typename T, typename N>
struct A_impl;

template<typename T, int N>
struct A_helper {
  typedef A_impl<T,N> type;
};
template<typename T>
struct A_helper<T,0> {
  typedef A0_impl<T> type;
};

template<typename T, int N=0>
using A = typename A_helper<T,N>::type;

template<typename T>
struct A0_impl {
  A0_impl() : mFoo(nullptr)    {}
  virtual ~A0_impl()        {}

  T* getFoo() { return mFoo; }
private:
  T* mFoo;
};
template<typename T, typename N>
struct A_impl:A0_impl<T> {
  A_impl() : A0_impl<T>(), mBar(N) {}
  virtual ~A_impl() {}

  int getBar() const { return mBar; }

protected:
  int mBar;
};
template<typename T>
struct A_impl<T,0>:A0_impl<T> {
  A_impl() : A0_impl<T>() {}
  virtual ~A_impl() {}
  // possibly inherit other constructors from A0_impl
};

这为您提供了与您的版本几乎完全相同的C ++代码,但却消除了您认为导致问题的专业下降问题。

基本上我将A<T,0>专精取代为A0_impltemplate别名A<T,N>现在映射到A_impl<T,N>A0_impl<T>,具体取决于N是否为0

A template别名是可选的,因为您可以将A0_impl称为AnySizedA,将A_impl称为FixedSizeA,并且而不是专门化A<T,0>来做某事只是禁止它。