c++ - 在 SWIG 中处理来自 self 的特殊实例的类继承

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

我有一些代码可以在 C++ 中编译并正常工作(只要我转发声明通用模板类,然后声明专用实例,然后定义通用模板类 - 请参阅 inheriting from class of specialized self?)。但是,当我尝试使用 SWIG 将 C# 绑定(bind)添加到类时,它要么使 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 的命令行参数,它可以使一切正常运行(并阻止它崩溃)?

最佳答案

我认为解决您的问题的最简单方法是,通过在 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_impl , 和 template别名 A<T,N>现在映射到 A_impl<T,N>A0_impl<T>取决于是否 N0还是不是。

A template别名是可选的,因为您可以使用 A0_impl被称为AnySizedAA_impl被称为FixedSizeA , 而不是专门研究 A<T,0>做某事只是禁止它。

关于c++ - 在 SWIG 中处理来自 self 的特殊实例的类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23000390/

相关文章:

c++ - 允许模板化类的结构化绑定(bind)

c# - DataContract 序列化 - 基类、继承和覆盖

c++ - 将 boost::chrono::steady_clock::time_point 转换为 std::chrono::steady_clock::time_point

c++ - Qt GUI 变得 react 迟钝,发出信号的速度太快

c++ - 写入和读取opencv3.0 ml文件(随机森林)

c++ - 公有继承自基类,私有(private)继承自派生类

CSS 继承被破坏?

c++ - 如何声明包含整数数组的对象

c++ - 虚函数的继承

c++ - 在 C++ 中使用 BitmapData 的 AccessVioilationException