使用SWIG和C ++模板函数

时间:2016-05-22 09:58:46

标签: c++ ruby swig

我在c ++中有一些map的模板函数,我想在ruby中使用它们。

template <class Collection>
const typename Collection::value_type::second_type& FindWithDefault(
    const Collection& collection,
    const typename Collection::value_type::first_type& key,
    const typename Collection::value_type::second_type& value) {
  typename Collection::const_iterator it = collection.find(key);
  if (it == collection.end()) {
    return value;
  }
  return it->second;
}

在c ++中,它的工作原理如下

int main(int argc, char const *argv[])
{
    typedef std::map<std::string, std::string> Map;
    Map m;
    std::string d= FindWithDefault(m, "foo", "");
    std::cout << d << "\n";
    //    
    m["foo"] = "bar";
    d=  FindWithDefault(m, "foo", "");
    std::cout << d << "\n";
    // bar
}

通过查看我之前回答过的问题的答案,可以很容易地利用地图并设置在红宝石中(看看here)。

至于这个问题我的界面文件有这个

%include <std_map.i>
namespace std {
   %template(IntMap) map<int,int>;
}
template <typename Collection>
const typename Collection::value_type::second_type& FindWithDefault(
    const Collection& collection,
    const typename Collection::value_type::first_type& key,
    const typename Collection::value_type::second_type& value) ;
%template(d) FindWithDefault<std::map<int,int> >;

我的c ++头文件具有上面提到的完整功能。现在,当我尝试在Irb中检查这个时,地图工作正常,但是我在使用模板函数时出错了

2.2.1 :001 > a = Example::IntMap.new
 => std::map<int,int,std::less< int >,std::allocator< std::pair< int const,int > > > {} 
2.2.1 :002 > a[1]=2
 => 2 
2.2.1 :003 > a[5]=3
 => 3 
2.2.1 :004 > a[4]=11
 => 11 
2.2.1 :005 > a
 => std::map<int,int,std::less< int >,std::allocator< std::pair< int const,int > > > {1=>2,4=>11,5=>3} 
2.2.1 :006 > b=Example::d(a,2,2)
ArgumentError: Wrong arguments for overloaded method 'd'.
Possible C/C++ prototypes are:
    std::map< int,int,std::less< int >,std::allocator< std::pair< int const,int > > >::value_type::second_type const & d(int a, int b)
    std::map< int,int,std::less< int >,std::allocator< std::pair< int const,int > > >::value_type::second_type const & d(std::map< int,int,std::less< int >,std::allocator< std::pair< int const,int > > > const &collection, std::map< int,int,std::less< int >,std::allocator< std::pair< int const,int > > >::value_type::first_type const &key, std::map< int,int,std::less< int >,std::allocator< std::pair< int const,int > > >::value_type::second_type const &value)

    from (irb):6:in `d'
    from (irb):6
    from /usr/share/rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'

我该如何做到这一点?

1 个答案:

答案 0 :(得分:2)

似乎SWIG无法确定Collection::value_type::first_typeCollection::value_type::second_type的类型。我不确定为什么。

在这种情况下恰好可行的解决方案/解决方法是将Collection::value_type::first_type替换为Collection::key_type,将Collection::value_type::second_type替换为Collection::mapped_type。在SWIG接口文件中执行此操作就足够了,即保持C ++代码不变,但将其放在接口文件中:

%include <std_map.i>
namespace std {
   %template(IntMap) map<int,int>;
}
template <typename Collection>
const typename Collection::mapped_type& FindWithDefault(
    const Collection& collection,
    const typename Collection::key_type& key,
    const typename Collection::mapped_type& value) ;
%template(d) FindWithDefault<std::map<int,int> >;