我有一些代码可以在 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>
取决于是否 N
是0
还是不是。
A
template
别名是可选的,因为您可以使用 A0_impl
被称为AnySizedA
和 A_impl
被称为FixedSizeA
, 而不是专门研究 A<T,0>
做某事只是禁止它。
关于c++ - 在 SWIG 中处理来自 self 的特殊实例的类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23000390/