Moved functors away from std_set.i and std_map.i

into their own std_functors.i file.
Made binarypredicate, etc. be templates to allow more
strict predicates/functors.




git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9815 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Gonzalo Garramuno 2007-05-16 22:48:01 +00:00
commit b20fd0d06f
5 changed files with 102 additions and 37 deletions

View file

@ -316,6 +316,10 @@ namespace swig {
} }
public: public:
ConstIterator_T() : ConstIterator(Qnil)
{
}
ConstIterator_T(const_iter curr, VALUE seq = Qnil) ConstIterator_T(const_iter curr, VALUE seq = Qnil)
: ConstIterator(seq), current(curr) : ConstIterator(seq), current(curr)
{ {
@ -326,6 +330,11 @@ namespace swig {
return current; return current;
} }
const value_type& operator*() const
{
return *current;
}
virtual VALUE inspect() const virtual VALUE inspect() const
{ {
VALUE ret = rb_str_new2("#<"); VALUE ret = rb_str_new2("#<");
@ -422,6 +431,16 @@ namespace swig {
*current = b; *current = b;
return *this; return *this;
} }
const value_type& operator*() const
{
return *current;
}
value_type& operator*()
{
return *current;
}
virtual VALUE inspect() const virtual VALUE inspect() const
{ {

View file

@ -8,7 +8,10 @@
* *
* You can use them in a swig file like: * You can use them in a swig file like:
* *
* %template< IntSet > std::set< int, RubyBinaryPredicate<> >; * %include <std_set.i>
* %include <std_functors.i>
*
* %template< IntSet > std::set< int, swig::BinaryPredicate<> >;
* *
* *
* which will then allow calling them from Ruby either like: * which will then allow calling them from Ruby either like:
@ -74,104 +77,120 @@ namespace swig {
$1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 2); $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 2);
} }
%typemap(in,noblock=1) UnaryFunction&, UnaryFunction { %typemap(in,noblock=1) BinaryFunction&, BinaryFunction {
$1 = new swig::UnaryFunction<>($input); $1 = new swig::BinaryFunction< >($input);
} }
%typemap(in,noblock=1) UnaryPredicate&, UnaryPredicate { %typemap(in,noblock=1) UnaryFunction&, UnaryFunction {
$1 = new swig::UnaryPredicate<>($input); $1 = new swig::UnaryFunction< >($input);
} }
%typemap(in,noblock=1) BinaryFunction&, BinaryFunction {
$1 = new swig::BinaryFunction<>($input);
}
%typemap(in,noblock=1) BinaryPredicate&, BinaryPredicate { %typemap(in,noblock=1) BinaryPredicate&, BinaryPredicate {
$1 = new swig::BinaryPredicate<>($input); $1 = new swig::BinaryPredicate<>($input);
} }
%typemap(in,noblock=1) UnaryPredicate&, UnaryPredicate {
$1 = new swig::UnaryPredicate< >($input);
}
%ignore BinaryFunction; %ignore BinaryFunction;
struct BinaryFunction {}; template< class _T = GC_VALUE >
struct BinaryFunction {
};
%ignore UnaryFunction; %ignore UnaryFunction;
struct UnaryFunction {}; template< class _T = GC_VALUE >
struct UnaryFunction {
};
%ignore BinaryPredicate; %ignore BinaryPredicate;
struct BinaryPredicate {}; template< class _T = GC_VALUE >
struct BinaryPredicate {
};
%ignore UnaryPredicate; %ignore UnaryPredicate;
struct UnaryPredicate {}; template< class _T = GC_VALUE >
struct UnaryPredicate {
};
} }
%{ %fragment("StdFunctors","header",fragment="StdTraits")
{
namespace swig { namespace swig {
static ID call_id = rb_intern("call"); static ID call_id = rb_intern("call");
template <class _DefaultFunc = std::less<GC_VALUE> > template <class _T = GC_VALUE, class _DefaultFunc = std::less<GC_VALUE> >
struct BinaryPredicate : GC_VALUE, std::binary_function<GC_VALUE, GC_VALUE, bool> struct BinaryPredicate : GC_VALUE, std::binary_function< _T, _T, bool >
{ {
BinaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } BinaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { }
bool operator()(GC_VALUE arg1, GC_VALUE arg2) const bool operator()(_T a, _T b) const
{ {
if (_obj != Qnil) { if (_obj != Qnil) {
SWIG_RUBY_THREAD_BEGIN_BLOCK; SWIG_RUBY_THREAD_BEGIN_BLOCK;
VALUE res = rb_funcall( _obj, swig::call_id, 2, VALUE arg1 = swig::from(a);
VALUE(arg1), VALUE(arg2)); VALUE arg2 = swig::from(b);
VALUE res = rb_funcall( _obj, swig::call_id, 2, arg1, arg2);
SWIG_RUBY_THREAD_END_BLOCK; SWIG_RUBY_THREAD_END_BLOCK;
return RTEST(res); return RTEST(res);
} else { } else {
return _DefaultFunc()(arg1, arg2); return _DefaultFunc()(a, b);
} }
} }
}; };
template <class _DefaultFunc = std::less<GC_VALUE> > template <class _T = GC_VALUE, class _DefaultFunc = std::less< _T > >
struct BinaryFunction : GC_VALUE, std::binary_function<GC_VALUE, GC_VALUE, GC_VALUE> struct BinaryFunction : GC_VALUE, std::binary_function< _T, _T, _T >
{ {
BinaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } BinaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { }
GC_VALUE operator()(GC_VALUE arg1, GC_VALUE arg2) const _T operator()(_T a, _T b) const
{ {
if (_obj != Qnil) { if (_obj != Qnil) {
SWIG_RUBY_THREAD_BEGIN_BLOCK; SWIG_RUBY_THREAD_BEGIN_BLOCK;
VALUE res = rb_funcall( _obj, swig::call_id, 2, VALUE arg1 = swig::from(a);
VALUE(arg1), VALUE(arg2)); VALUE arg2 = swig::from(b);
VALUE res = rb_funcall( _obj, swig::call_id, 2, arg1, arg2);
SWIG_RUBY_THREAD_END_BLOCK; SWIG_RUBY_THREAD_END_BLOCK;
return GC_VALUE(res); return swig::as<_T >(res);
} else { } else {
return _DefaultFunc()(arg1, arg2); return _DefaultFunc()(a, b);
} }
} }
}; };
template< class _T = GC_VALUE >
struct UnaryPredicate : GC_VALUE, std::unary_function<GC_VALUE, bool> struct UnaryPredicate : GC_VALUE, std::unary_function< _T, bool >
{ {
UnaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } UnaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { }
bool operator()(GC_VALUE arg1) const bool operator()(_T a) const
{ {
SWIG_RUBY_THREAD_BEGIN_BLOCK; SWIG_RUBY_THREAD_BEGIN_BLOCK;
VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1)); VALUE arg1 = swig::from<_T >(a);
VALUE res = rb_funcall( _obj, swig::call_id, 1, arg1);
SWIG_RUBY_THREAD_END_BLOCK; SWIG_RUBY_THREAD_END_BLOCK;
return RTEST(res); return RTEST(res);
} }
}; };
struct UnaryFunction : GC_VALUE, std::unary_function<GC_VALUE, GC_VALUE> template< class _T = GC_VALUE >
struct UnaryFunction : GC_VALUE, std::unary_function< _T, _T >
{ {
UnaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } UnaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { }
GC_VALUE operator()(GC_VALUE arg1) const _T operator()(_T a) const
{ {
SWIG_RUBY_THREAD_BEGIN_BLOCK; SWIG_RUBY_THREAD_BEGIN_BLOCK;
VALUE arg1 = swig::from(a);
VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1)); VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1));
SWIG_RUBY_THREAD_END_BLOCK; SWIG_RUBY_THREAD_END_BLOCK;
return GC_VALUE(res); return swig::as< _T >(res);
} }
}; };
} // namespace swig
} }
%}

29
Lib/ruby/std_functors.i Normal file
View file

@ -0,0 +1,29 @@
/**
* @file std_functors.i
* @date Sun May 6 00:44:33 2007
*
* @brief This file provides unary and binary functors for STL
* containers, that will invoke a Ruby proc or method to do
* their operation.
*
* You can use them in a swig file like:
*
* %include <std_set.i>
* %include <std_functors.i>
*
* %template< IntSet > std::set< int, swig::BinaryPredicate<int> >;
*
*
* which will then allow calling them from Ruby either like:
*
* # order of set is defined by C++ default
* a = IntSet.new
*
* # sort order defined by Ruby proc
* b = IntSet.new( proc { |a,b| a > b } )
*
*/
%include <rubystdfunctors.swg>
%fragment("StdFunctors");

View file

@ -403,8 +403,6 @@
%mixin std::map "Enumerable"; %mixin std::map "Enumerable";
%include <rubystdfunctors.swg>
%rename("delete") std::map::__delete__; %rename("delete") std::map::__delete__;
%rename("reject!") std::map::reject_bang; %rename("reject!") std::map::reject_bang;

View file

@ -60,7 +60,6 @@
%mixin std::set "Enumerable"; %mixin std::set "Enumerable";
%include <rubystdfunctors.swg>
%rename("delete") std::set::__delete__; %rename("delete") std::set::__delete__;
@ -74,3 +73,4 @@
%include <std/std_set.i> %include <std/std_set.i>