473,387 Members | 1,515 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Want feedback on C++ version of Python's explode operator

Python has a nifty operator that will take a container and pass its
elements as function parameters. In Python you can make a list like
so:

x = [1, 2, 3]

Then you can say:

f(*x)

Which is the same as f(x[0], x[1], x[2]). I thought it would be nice
to have the same functionality for C++. I've written an implementation
of it, that lets you write things like this:

int sum(int x, int y) { return x + y; }

boost::array<int, 2operands = { 3, 4 };
boost::function<int(int, int)Sum = sum;
explode(Sum, operands); // Same as writing sum(operands[0],
operands[1])

It makes heavy use of template and boost preprocessor magic, but it
seems to work. I'm looking for feedback on how to improve it (it looks
rather obfuscated). I'm still new to heavy template usage and so their
might be better ways to accomplish this. Right now it's limited to
working on containers that are of a type with a static_size member
defining their size (like boost::array has), but should be easily
expandable to working on builtin arrays, specified ranges, etc.

I've divided it up into three files:
1. bind_append.hpp -- Defines a wrapper around boost::bind that
assumes you want to bind a parameter to the end of the parameter list
and leave the rest of the parameters alone in normal order.
2. remove_arg.hpp -- A function trait that gives you the same function
type with one parameter removed.
3. explode.hpp -- implementation of explode()

// ===========bind_append.hpp=================
/*
Author: Joseph Garvin (2006)

bindappend is a wrapper around boost::bind that assumes you want to
append
1 argument to the current function object, immediately to the end of
the
argument list, and want to leave placeholders, in order, for the
rest. It's
less flexible than bind but combined with remove_arg is useful for
iteratively
applying parameters to a function. Example:

int sum(int x, int y, int z) { return x + y + z; }

bindappend(sum, 3) // Equivalent to bind(sum, 3, _1, 2)
*/

#ifndef BOOST_PP_IS_ITERATING

#ifndef INCLUDED_BIND_APPEND_H
#define INCLUDED_BIND_APPEND_H

#include <boost/preprocessor/repetition.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <meta/remove_arg.hpp>

using namespace boost;

template<class FuncType, class ParamType, int remainingArity>
struct bindappend_impl
{
// Error! We have no remaining arity!
BOOST_STATIC_ASSERT ( sizeof ( ParamType ) == 0 );
};

#ifndef BIND_APPEND_MAX_SIZE
#define BIND_APPEND_MAX_SIZE 8
#endif

#define BOOST_PP_ITERATION_LIMITS (0, BIND_APPEND_MAX_SIZE)
#define BOOST_PP_FILENAME_1 <bind_append.hpp>
#include BOOST_PP_ITERATE()

template<class FuncType, class ParamType>
function<typename remove_arg<FuncType>::type>
bind_append(function<FuncTypefunc, ParamType param)
{
return bindappend_impl<FuncType, ParamType,
function_traits<FuncType>::arity - 1>::bind_append(func, param);
}

#endif // INCLUDED_BIND_APPEND_H

#else // BOOST_PP_IS_ITERATING

#define n BOOST_PP_ITERATION()

template<class FuncType, class ParamType>
struct bindappend_impl <FuncType, ParamType, n>
{
static function<typename remove_arg<FuncType>::type>
bind_append(function<FuncTypefunc, ParamType param);
};

template<class FuncType, class ParamType>
function<typename remove_arg<FuncType>::type>
bindappend_impl<FuncType, ParamType,
n>::bind_append(function<FuncTypefunc, ParamType param)
{
return bind(func, param BOOST_PP_COMMA_IF (n)
BOOST_PP_ENUM_SHIFTED_PARAMS (BOOST_PP_ADD(n, 1), _) );
}

#undef n

#endif // BOOST_PP_IS_ITERATING
// ===========remove_arg.hpp=================
/*
Author: Joseph Garvin (2006)

remove_arg is a compile time function that takes a function type and
returns
the same function type with one less argument. E.g. it transforms:

int(char, float, double)

To:

int(float, double)

Example Usage:

boost::function<remove_arg<FuncType foo = boost::bind_append(foo,
x);
*/

#ifndef BOOST_PP_IS_ITERATING

#ifndef INCLUDED_REMOVE_ARG_H
#define INCLUDED_REMOVE_ARG_H

#include <boost/preprocessor/repetition.hpp>
#include <boost/static_assert.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>

template<typename R>
struct remove_arg
{
// Error! We have no parameters to strip!
BOOST_STATIC_ASSERT ( sizeof ( R ) == 0 );
};

#ifndef REMOVE_ARG_MAX_SIZE
#define REMOVE_ARG_MAX_SIZE 8
#endif

#define BOOST_PP_ITERATION_LIMITS (1, REMOVE_ARG_MAX_SIZE)
#define BOOST_PP_FILENAME_1 <remove_arg.hpp>
#include BOOST_PP_ITERATE()

#endif // INCLUDED_REMOVE_ARG_H

#else // BOOST_PP_IS_ITERATING

#define n BOOST_PP_ITERATION()

template <class R BOOST_PP_COMMA_IF ( n ) BOOST_PP_ENUM_PARAMS ( n,
class T ) >
struct remove_arg <R ( BOOST_PP_ENUM_PARAMS ( n,T ) ) >
{
typedef R type ( BOOST_PP_ENUM_SHIFTED_PARAMS (n, T ) );
};

#undef n

#endif // BOOST_PP_IS_ITERATING
// ===========explode.hpp=================
#include <boost/function.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/bind.hpp>
#include <boost/static_assert.hpp>

#include <meta/remove_arg.hpp>
#include <meta/bind_append.hpp>

template<class FuncSig, class FixedSizeSTLContainer, int arity>
class Explode_Helper
{
public:
static typename function_traits<FuncSig>::result_type
explode_helper(function<FuncSigfunc, FixedSizeSTLContainer args);
};

template<class FuncSig, class FixedSizeSTLContainer, int arity>
typename function_traits<FuncSig>::result_type
Explode_Helper<FuncSig, FixedSizeSTLContainer,
arity>::explode_helper(function<FuncSigfunc, FixedSizeSTLContainer
args)
{
function<typename remove_arg<FuncSig>::type appliedFunc =
bind_append(func, args[FixedSizeSTLContainer::static_size - arity]);
return Explode_Helper<
typename remove_arg<FuncSig>::type,
FixedSizeSTLContainer,
function_traits<typename remove_arg<FuncSig>::type>::arity
>
::
explode_helper(appliedFunc, args);
}

template<class FuncSig, class FixedSizeSTLContainer>
class Explode_Helper<FuncSig, FixedSizeSTLContainer, 0>
{
public:
static typename function_traits<FuncSig>::result_type
explode_helper(function<FuncSigfunc, FixedSizeSTLContainer args);
};

template<class FuncSig, class FixedSizeSTLContainer>
typename function_traits<FuncSig>::result_type
Explode_Helper<FuncSig, FixedSizeSTLContainer,
0>::explode_helper(function<FuncSigfunc, FixedSizeSTLContainer args)
{
return func();
}

template<class FuncSig, class FixedSizeSTLContainer>
typename function_traits<FuncSig>::result_type
explode(function<FuncSigfunc, FixedSizeSTLContainer args)
{
BOOST_STATIC_ASSERT ( function_traits<FuncSig>::arity ==
FixedSizeSTLContainer::static_size );

return Explode_Helper<FuncSig, FixedSizeSTLContainer,
function_traits<FuncSig>::arity>::explode_helper(f unc, args);
}

Feb 6 '07 #1
0 1947

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Robert Brewer | last post by:
WARNING: The following is NOT all Pythonic. However, it is Python. This is just fun--nothing I'm going to put into production. I don't have any questions or problems--just thought I'd share. ...
4
by: Dan Perl | last post by:
pyfmf is a project I started a few months ago and that is registered with sourceforge (http://pyfmf.sourceforge.net, http://sourceforge.net/projects/pyfmf). It consists of a framework for file...
9
by: christopher diggins | last post by:
I would like some feedback if the follow code is standard compliant, and are there any obvious redundancies or inefficiencies? The purpose of the code is to emulate the behaviour of a struct FuBar...
17
by: JKop | last post by:
G++ gives the most un-informative, cryptic, BULLSHIT errors statements. I'm writing a program at the moment and I have to finish it real soon. The problem I'm having is illustrated in the...
5
by: David Coppit | last post by:
Hi all, Most smart pointers remove the need to call delete. What I want is a pointer that turns delete into a no-op for "unauthorized" clients. The reason is that I'm generating code from...
10
by: mwt | last post by:
This code works fine to download files from the web and write them to the local drive: import urllib f = urllib.urlopen("http://www.python.org/blah/blah.zip") g = f.read() file =...
17
by: Ron Adam | last post by:
I put together the following module today and would like some feedback on any obvious problems. Or even opinions of weather or not it is a good approach. While collating is not a difficult thing...
0
by: Tor Erik Soenvisen | last post by:
Hi, all I would like some feedback on a multithreaded HTTP server I've written. The server serves python-scripts by dynamically loading scripts in the same directory as itself. When a request is...
15
by: skip | last post by:
If you're an Emacs user who has used both python-mode.el (the python mode code distributed with Python and XEmacs) and python.el (the python mode code distributed with GNU Emacs), I'd like to get...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.