|
Boost : |
From: Torsten Mähne (Torsten.Maehne_at_[hidden])
Date: 2008-05-28 06:25:16
Hello,
I'm pleased to see so much activity in the development of Boost.Units
recently. I try to apply it myself in some code to model physical
systems. There it helps me a lot to ensure the correct use of the model
parameters inside the model equations and to ensure the correct
composition of components to a system model. Certain component
behaviour, I would like to parametrize for each component instance by
passing a functor describing, e.g., a signal waveform or a non-linear
relation between to quantities. I therefore tried to combine Boost.Units
with Boost.Lambda and Boost.Function.
I noticed that currently Units and Lambda use two independent systems of
trait classes to determine the return type of algebraic operations like
+, -, *, /. This requires to litter the lambda expression with a lot of
ret<return_type>(...) function calls to construct a functor containing
boost::units::quantity<U, V> instances. However, the trait classes used
by Units and Lambda are very similar, so I created as a first solution a
header file <lambda.hpp> (see attachment), which extends Boost.Lambda's
return type reduction system through partial specialization to use
Boost.Units' trait classes in case boost::unit::quantity<U,V> are
involved in operator[+|-|*|/]() calls. Maybe it's also useful for others
and could even become part of Boost.Units after some further
improvements. However, there are some open issues:
- Can some of the partial specializations be dropped?
- Is there a need to add other specializations
(e.g, for boost::units::unit<Dim, System, Enable>)?
- Is there a way to work around boost::lambda:bind's limitation
concerning the binding of overloaded functions? The required
static_cast to the function pointer (referring, e.g., a function
from boost/units/cmath.hpp) is tedious.
The attached small test program <units_with_lambda_test.cpp>
demonstrates its usage and tedious bind issue, for which I haven't found
a solution yet. Boost.Lambda requires calls to functions to be postponed
using boost::lambda::bind(), so that they are executed not only once
upon functor creation but at each functor call. Bind has the unfortunate
limitation that it cannot resolve calls to overloaded functions. Thus,
each time a call to an overloaded function (e.g., all functions defined
in <boost/units/cmath.hpp>) is made, a lengthy static_cast<return_type
(*)(argument_type)>(function_name) is needed for the first bind argument
to help the compiler to find the overloaded function, which can accept
the function arguments passed by the other bind arguments. Could this be
somehow avoided or at least the syntax simplified? I'm thinking of,
e.g., a templated function or (more ugly) a preprocessor macro adding
the required static_cast based on some trait class or typeof.
I'm looking forward to your feedback.
Best regards,
Torsten Maehne
.DEFAULT_GOAL := all
# Install locations of Boost 1.35 and Boost.Units
BOOSTROOT := /opt/boost_1_35_0
BOOSTUNITS := /opt/boost_units
CPPFLAGS := -I$(BOOSTROOT)/boost/tr1/tr1 -I$(BOOSTROOT) -I$(BOOSTUNITS)
CXXFLAGS := -g -Wall
% : %.o
$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ | c++filt
.PHONY : all clean
all : units_with_lambda_test
units_with_lambda_test : units_with_lambda_test.o
units_with_lambda_test.o : units_with_lambda_test.cpp lambda.hpp
clean :
-rm units_with_lambda_test *.o *~ semantic.cache
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk