template< bool IS_CONST >
class Handle
{
public:
Handle(void) : m_value(0) { }
Handle(int value) : m_value(value) { }
template < bool T = IS_CONST, typename COMPILED = typename std::enable_if< T == false >::type >
void set(int value)
{
m_value = value;
}
int get(void) const
{
return m_value;
}
private:
int m_value;
};
这段代码按预期编译了一个作品:Handle< true >
没有set
方法,Handle< false >
有它。你知道吗
现在我正在尝试使用SWIG将其绑定到Python。我正在使用以下文件生成绑定:
%module core
%include "Handle.h"
%template(NonConstHandle) Handle< false >;
%template(ConstHandle) Handle< false >;
%{
#include "Test.h"
%}
SWIG毫无怨言地生成模块,它编译得很好,但是set
方法从不绑定,即使在专门的NonConstHandle
中也是如此。e、 g.以下Python测试因AttributeError: 'NonConstHandle' object has no attribute 'set'
而失败:
import core
handle = core.NonConstHandle()
assert(handle.get() == 0)
handle.set(1)
assert(handle.get() == 1)
const_handle = core.ConstHandle()
assert(const_handle .get() == 0)
try:
const_handle .set(1)
print("this should not print")
except:
pass
print("all good")
当我搜索这个主题时,我发现了很多与enable\u if和SWIG相关的东西,这让我觉得它是受支持的,但是我不明白为什么没有生成set
,尽管SWIG没有发出错误/警告。。。你知道吗
感谢您的帮助! 敬礼
问题在于,每次在C++中创建模板时,在SWIG接口中至少需要一个^ {{CD1>}指令,以便对生成的包装器有任何影响。你知道吗
当人们含糊地暗示
std::enable_if
有效时,他们通常意味着两件事。首先它解析的是ok,其次是%template
对它们有效。这两件事在这里都是真的。你知道吗由于在模板类中使用了SFINAE和模板函数,因此每个函数都需要一个
%template
。否则set
成员将被完全忽略,如您所见。如果你的问题有一点是一个好的开始,那么跳过SFINAE/enable\u是一个好的开始。你知道吗我们可以把你的.i文件改成这样:
问题是(修复了其中的一些小错误)您的测试python现在遇到了“this should not print”,因为我们已经生成了一个(完全合法的)
set()
函数,即使在const情况下也是通过显式地拼写模板参数,而不是推导它们。你知道吗所以我们生成了要调用的代码:
它在这个例子中是有效的,因为它不能以直观的方式编译。你知道吗
我不知道有什么方法可以在这里进行扣减(这很遗憾,因为它们是默认的,所以应该可以对吗?-也许有一个是为了给SWIG trunk打补丁,尽管做default和SFINAE都会很棘手)
幸运的是,有一个简单的解决方法,使用
%ignore
删除我们不想要的版本:%模块测试
它会生成您期望的代码。你知道吗
值得注意的是,在生成包装器时,通常更容易显式地说明您希望复杂模板化代码的工作方式—您通常需要对接口进行额外的帮助或调整,以使其以您希望的方式在Python中工作。所以你也可以通过这样做来解决你的例子:
或者类似的伎俩:
但是请注意,在最后一种情况下,如果要将模板用作函数中的参数或函数外的参数,则还需要使用
%apply
。你知道吗相关问题 更多 >
编程相关推荐