
In PStade Egg it was called [ambi] (
http://p-stade.sourceforge.net/boost/libs/egg/doc/html/boost_egg/function_ad...
), but you have to specify the number of parameters of the function.
But ambiN only works with function objects, or am I wrong?
Yes, but function objects is a much better way to declare polymorphic functions(unless they require an explicit template parameter).
I created one for a library I am writing, you can see the source code for pipable here: https://github.com/pfultz2/Zen/blob/master/zen/function/pipable.h
In the example at the top the syntax seem different from the test in the bottom of the file,
The example is showing how to make a function pipable in place, and the test at the bottom is testing its use with `static_`.(of course, I just realized there is a mistake in the example) I probably should add an in place test as well. The example doesn't use `static_` to help keep the example simple without having to figure what `static_` does in order figure out what pipable does. However, using `static_` is more likely how it will be used in practice. For example, say we define our sum function object, like this: struct sum_f { template<class T> T operator()(T x, T y) const { return x+y; } }; If we want to make this work as a function we need to static initialize it: sum_f sum = {}; Which works fine, but if we want to make it pipable, we could try this: pipable_adaptor<sum_f> sum = {}; Which will work on C++11, but not on non-C++11 compilers, since the requirement for static initializtion(ie an aggregate type) is quite strict. So the `static_` adaptor can be used to static initialize any default constructible function object, like this: static_<pipable_adaptor<sum_f> > sum = {};
how how you specify a pipeable wrapper for, for example boost::range::accumulate?
Thats a really interesting example, since it has two overloads of different arity. This requires using some template constraints to avoid incorrect arity detection. Something like this(of course assuming we have the traits `is_range` and `is_range_of`): struct accumulate_f { template<class X> struct result; template<class X, class Range, class T> struct result<X(Range, T)> : boost::decay<T> {}; template<class X, class Range, class T, class BinaryOp> struct result<X(Range, T, BinaryOp)> : boost::decay<T> {}; template<class Range, class T> typename enable_if<and_<is_range<Range>, is_range_of<Range, T> >, T>::type operator()(Range& r, T init) const { return std::accumulate(boost::begin(r), boost::end(r), init); } template<class Range, class T, class BinaryOp> typename enable_if<and_<is_range<Range>, is_range_of<Range, T> >, T>::type T operator()(Range& r, T init, BinaryOp op) const { return std::accumulate(boost::begin(r), boost::end(r), init, op); } }; static_<pipable_adaptor<accumulate_f> > accumulate = {}; Then we would use it something like this: std::vector<int> numbers = { 1, 2, 3, 4 }; assert(10 == numbers | accumulate(0)); assert(10 == accumulate(numbers, 0)); Although I haven't tested this yet. Paul
/Viktor
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost