Using a boost::numeric::odeint stepper inside a complicated class - c++

I have an extremely convoluted system of numerical rate equations, which are to be solved by the class ElectronSolver. The electron state is handled by a separate class state_type, not shown here.
A simplified template of the problem class appears as
ElectronSolver.h
class ElectronSolver {
public:
ElectronSolver(const char* filename, ofstream& log);
void solve();
void print(const std::string& fname);
std::vector<double> T; // Times, in fs
std::vector<state_type> Y; // stores the state_t's
private:
// steps, State, value, Derivative, Time, Algebra
adams_bashforth_moulton< 5, state_type, double, state_type, double, vector_space_algebra > abm;
void set_initial_conditions();
// Model parameters
PhotonFlux pf;
void sys(const state_type& s, state_type& sdot, const double t);
};
ElectronSolver.cpp
void ElectronSolver::set_initial_conditions(){
// Set the initial T such that pulse peak occurs at T=0
T[0] = -timespan/2;
Y[0] = state_type(Store, num_elec_points);
abm.initialize( sys, Y[0], T[0], dt ); // This line produces an error
}
void ElectronSolver::sys(const state_type& s, state_type& sdot, const double t){
// complicated system modifying sdot
sdot.flux += pf(t)*s.flux;
}
However, some research revealed why the marked line throws a compile error.
As far as I can understand sys as declared here must be called "on a class", so cannot simply be passed as a reference. This question got around that by declaring sys as static, but that won't work here since I'm relying on calling other members of ElectronSolver in sys.
There is little concievable reason that I would need multiple instances of ElectronSolver, but I would like to leave the option there in case any code maintainers want to have two different electron models.
As far as I can tell, I have four options:
make everything sys needs static (less than desirable due to ElectronSolver inheriting from other classes, but doable)
Construct some kind of a wrapper for the sys function (possibly has a performance hit, and more to the point, I don't know how to do this)
Implement the ODE stepper myself to avoid the headaches of using boost.
????
Which solution strikes the best bargain between
- Performance (though the largest performance bottleneck is probably the time it takes sys to execute)
- Code elegance
- Modularity
?

Whether or not you want to continue using boost is a decision only you can make, but it's easy to create a wrapper with no performance hit.
You'll want to wrap sys in a lambda that captures this. This should not have a performance hit, as the lambda will be inlined when optimizations are turned on.
You would call it like this:
abm.initialize(
[this](const state_type& s, state_type& sdot, const double t) {
this->sys(s, sdot, t);
},
Y[0],
T[0],
dt
);
The lambda is basically an implicit wrapper struct that holds a reference to this and defines an operator()(const state_type& s, state_type& sdot, const double t).
I created an example in godbolt that shows this, simplifying and filling in your code where necessary for the example. If you change the optimization between -O0 and -O3 you can see the lambda code is stripped away and the inner method is fully inlined.
Another option is use std::bind to create a bare function out of the member function:
abm.initialize(
std::bind(&ElectronSolver::sys, std::ref(*this), _1, _2, _3),
Y[0],
T[0],
dt
);
along with this elsewhere:
#include <functional>
using namespace std::placeholders;
to get all the symbols into scope. std::bind creates a new function where the some arguments are already filled in. In this case the implicit first argument, the object itself, is filled in with a reference to this. The rest of the arguments are given special placeholders to indicate the new function will fill them in with its arguments. The std::ref, forces taking this by reference rather than by copy. This method will also have zero overhead.

Related

How can i put function with different parameters into map in c++?

I need to design a map, which save all function i may use in the futures.
all the functions will have double as its return value.
and all function share a common parameters const std::vector<float>&
so i define the map as:
typedef std::function<double(const std::vector<float>&)> func;
std::unordered_map<std::string, func> f_map;
for example. if i have a function looks like:
double func1(const std::vector<float>& v) {
return 0.; // just a demo
}
i can put it into map like this:
f_map.emplace("2015", static_cast<double(*)(const std::vector<float>&)>(func1));
it's ok since i tested it.
but the problem is:
i also have some function like this:
double func2(int a, const std::vector<float>& v) {
return 0.; // just for demo
}
how can i input this kind of function in my map?
std::bind doesnt work if i do like this:
f_map.emplace("2000", static_cast<double(*)(const std::vector<float>&)>(std::bind(func2, 1)));
can you help on this?
and can you give me your advice on how to save function into map better, thanks very much
What you're asking is essentially the same as:
How can I store both int and float in a map and use them equally?
Functions with different parameters are simply different. A map can only hold a single type. Suppose you get function "2019", how will you or the compiler ever know what kind of function it is?
There are a couple of ways to solve this problem. The essence is to have them be the same type. With std::bind you're on the right track. The correct way to use bind with parameters is to use the std::placeholders.
Say we have this function, double DoThing(int num, std::vector<float>& vec), and wish to fill in the first parameter, but leave the second one open for later. We can do:
mymap.emplace("2000", std::bind(&DoThing, 123, std::placeholders::_1));
You are free to shift the placeholder around however you like and add other ones too.
If you store the object bind returns and later get it back you can call it like so:
mymap["2000"](vec); //will call DoThing(123, vec)
Also. std::bind returns an object that holds both the function pointer to DoThing and any value you prefilled as well. Casting this to a function pointer like you did is not possible. That object is not a problem here since std::function, the map's contained type, has functionality to also store and, later, be able to call this object correctly.
Simillarly you can use lambda's to achieve the same effect as bind:
mymap.emplace("2000", [](std::vector<float>& vec){ return DoThing(123, vec); });
Other possibilities include unions/variants or other possibly tricky stuff. Though these methods will only make your code more complex if you don't know how to use them, so I don't recommend these.
Avoiding type casts is better and more safe. The first emplace [1] is valid without static_cast.
You should inform std::bind where to place the unbound argument with help of placeholders [2]. _1 of the namespace std::placeholders sets the unbound argument v to be the first argument of the resulting functional object.
If you use not capturing lamba expression, you can store pointers to functions. Pointers take less bytes than std::function objects. See [3].
#include <functional>
#include <string>
#include <unordered_map>
double func1(const std::vector<float>&) {
return 0.; // just a demo
}
double func2(int, const std::vector<float>&) {
return 0.; // just for demo
}
int main() {
using namespace std::placeholders;
typedef std::function<double(const std::vector<float>&)> func;
std::unordered_map<std::string, func> f_map;
f_map.emplace("2015", func1); // [1]
f_map.emplace("2000", std::bind(func2, 1, _1)); // [2]
// [3]
typedef double(*pfunc)(const std::vector<float>&);
std::unordered_map<std::string, pfunc> f_map2;
f_map2.emplace("2015", func1);
f_map2.emplace("2000", [](const std::vector<float>&v) { return func2(1, v); });
}

Relying on compiler optimizations with C++ [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Question: is it OK to rely on compiler optimizations while coding?
Let's say I need to calculate calculateF and calcuateG which both depend on another value returned by getValue. Sometimes I need both values, some other times I only need one of those values.
// some function
double getValue(double value)
{
double val(0.0);
// do some math with value
return val;
}
// calculateF depends on getValue
double calculateF(double value)
{
double f(0.0);
auto val = getValue(value);
// calculate f which depends on val (and value)
return f;
}
// calculateG depends on getValue
double calculateG(double value)
{
double g(0.0);
auto val = getValue(value);
// calculate g which depends on val (and value)
return g;
}
Now, I could write this more elegantly:
std::pair<double,double> calculateFG(double value)
{
auto val = getValue(value);
double f(0.0), g(0.0);
// calculate f and g which depend on val (and value)
return {f,g};
}
If I want both values:
double value(5.3);
auto [f,g] = calculateFG(value); // since C++17
// do things with f and g
If I want only 1 value, say f, I just don't use g and it will be optimized out. So, the performance of calculateFG is exactly the same as calculateF if I don't use g. Furthermore, if I need both f and g, I only need to call getValue once instead of twice.
The code is cleaner (only 1 function calculateFG instead of calculateF and calculateG), and faster if both f and g are required. But is relying on the compiler optimization a wise choice?
It is hard to say if it is wise or not. It depends on compiler optimization - function inlining.
If calculateFG is inlined, the complier can optimize out the unused one. Once inlined, g is unused so all the code for generating g is dead code[1]. (It may not be able, for example, if the calculation code has some side effects)
If not, I don't think the optimization can be applied(Always calc f and g).
Now you may wonder if it is possible to always inline specific functions.
Please note that giving inline keyword does not force the compiler to inline that function. It is just a hint. With or without the keyword, it is the compiler's call. It seems like there is non-standard way though - How do I force gcc to inline a function?
[1]Relavent compiler options : -fdce -fdse -ftree-dce -ftree-dse
Modern C++ compilers are pretty good at optimization choices, given the chance.
That is to say, if you declare a function inline, that does not mean the optimizer will actually ilnine it 100% of the time. The effect is more subtle: inline means you avoid the One Definition Rule, so the function definition can go into header files. That makes it a lot easier for the optimizer.
Now with your examples of double [f,g], optimizers are very good at tracking the use of simple scalar values, and will be able to eliminate write-only operations. Inlining allows the optimizer to eliminate unnecessary writes in called functions too. For you, that means the optimizer can eliminate writes to f in calculateFG when the calling code does not use f later on.
Perhaps it is best to turn the logic inside-out. Instead of computing a value (getValue()), passing it to both calculateF() and calculateG(), and passing the results to another place, you can change the code to pass the functions instead of computed values.
This way, if the client code does not need calculateF's value, it won't call it. The same with calculateG. If getValue is also expensive, you can call it once and bind or capture the value.
These are concepts used extensively in functional programming paradigm.
You could rewrite your calculateFG() function more or less like this:
auto getFG(double value)
{
auto val = getValue(value);
return {
[val]{ return calculateF(val); },
[val]{ return calculateG(val); }};
}
It sounds like your goal is to only perform the (potentially expensive) calculations of getValue(), f, and g as few times as possible given the caller's needs -- i.e. you don't want to perform any computations that the caller isn't going to use the results of.
In that case, it might be simplest to just implement a little class that does the necessary on-demand computations and caching, something like this:
#include <stdio.h>
#include <math.h>
class MyCalc
{
public:
MyCalc(double inputValue)
: _inputValue(inputValue), _vCalculated(false), _fCalculated(false), _gCalculated(false)
{
/* empty */
}
double getF() const
{
if (_fCalculated == false)
{
_f = calculateF();
_fCalculated = true;
}
return _f;
}
double getG() const
{
if (_gCalculated == false)
{
_g = calculateG();
_gCalculated = true;
}
return _g;
}
private:
const double _inputValue;
double getV() const
{
if (_vCalculated == false)
{
_v = calculateV();
_vCalculated = true;
}
return _v;
}
mutable bool _vCalculated;
mutable double _v;
mutable bool _fCalculated;
mutable double _f;
mutable bool _gCalculated;
mutable double _g;
// Expensive math routines below; we only want to call these (at most) one time
double calculateV() const {printf("calculateV called!\n"); return _inputValue*sin(2.14159);}
double calculateF() const {printf("calculateF called!\n"); return getV()*cos(2.14159);}
double calculateG() const {printf("calculateG called!\n"); return getV()*tan(2.14159);}
};
// unit test/demo
int main()
{
{
printf("\nTest 1: Calling only getF()\n");
MyCalc c(1.5555);
printf("f=%f\n", c.getF());
}
{
printf("\nTest 2: Calling only getG()\n");
MyCalc c(1.5555);
printf("g=%f\n", c.getG());
}
{
printf("\nTest 3: Calling both getF and getG()\n");
MyCalc c(1.5555);
printf("f=%f g=%f\n", c.getF(), c.getG());
}
return 0;
}
I think that it's best to write your code in a way that expresses what you are trying to accomplish.
If your goal is to make sure that certain calculations are only done once, use something like Jeremy's answer.
A good function should do only one thing. I would design like below.
class Calc {
public:
Calc(double value) : value{value}, val{getValue(value)} {
}
double calculateF() const;
double calculateG() const;
//If it is really a common usecase to call both together
std::pair<double, double> calculateFG() const {
return {calculateF(), calculateG()};
}
static double getValue(double value);
private:
double value;
double val;
};
To know whether compiler will optimize will depend on the rest of the code. For example, if there was a debug message like log_debug(...), that could affect dead code removal. Compiler can only get rid of the dead code if it can prove that the code has no side effects in compile time (Even if you force inline).
Other option is, you can mark the getValue function with special compiler specific attributes like pure or const. This can force the compiler to optimize the second call of getValue. https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007bpure_007d-function-attribute-3348

How to return optional debug information from a method?

Lets say I have a static method which compares two objects for a close match and returns some confidence level [0,1].
class Foo
{
...
static double Compare(const Foo& foo1, const Foo& foo2);
...
};
Now I need to return additional debug information containing comparison details depending on a setting in the configuration.
Since this debug information won't be used at production, but only in testing/debugging purposes I was wondering what is the appropriate way to implement it.
I see at least three options:
1: Create an additional class CompareResult and store confidence + optional info there. Don't populate the optional info if you don't need to.
class CompareResult
{
...
private:
double confidence_;
CompareOptionalInfo compare_optional_info_;
...
};
...
static CompareResult Compare(const Foo& foo1, const Foo& foo2);
It seems to be the cleanest one, but I'm not sure if I should combine return result with an optional info.
2: Use output variable (this way we won't need to create an additional class, but our method signature will grow a bit)
static double Compare(const Foo& foo1, const Foo& foo2, CompareOptionalInfo* out_compare_info = nullptr);
3: Separate compare method with optional-info retrieval method.
static double Compare(const Foo& foo1, const Foo& foo2);
static CompareOptionalInfo GetCompareOptionalInfo();
This option would probably require to store this optional-info between the method invocations and shift from static compare method to the instance compare method.
But again, I'm not sure if it is appropriate or not.
From your experience, what is the appropriate way in OOP world to return optional information (which will be mostly used only in debug mode) from a method?
Option 3 is not a good idea at all : having functions depending on static data is not practical and could become even be a source of bugs in the debugging. Such a design is in addition not be thread safe ; what a pity it would be, to create such a restriction only for debugging purpose !
Examples of problems:
double closest = std::max (Foo::compare (x, y), Foo::compare (y,z));
clog << Foo::GetCompareOptionalInfo(); // undefined which info since order of eval
// of function parameter is not guaranteed
double d = Foo::compare (x, y);
DoSomething(); // what if this one does an unexpected compare ?
clog << Foo::GetCompareOptionalInfo();
Option 2 is a viable solution, but it's not very convenient: it forces you to create info objects, pass them by address etc:
Foo::OptionalCompareInfo o1,o2; // cumbersome
double closest = std::max (Foo::compare (x, y, &o1), Foo::compare (y,z, &o2));
In addition, you would create these optional infos and pass the extra argument in production as well, even if you no longer update the info there (unless you put a lot of extra conditional compilation) !
Option 1 is excellent ! Go for it ! It really takes benefit of the OOP paradigm and uses a clean design. It's practical to use and don't impose constraints on your code to use it.
All you need is to provide some (implicit) conversion function to use your CompareResult almost as if it were a double:
class CompareResult
{
public:
CompareResult(double d=0.0) : confidence_(d) {};
operator double() { return confidence_; }
operator bool() { return confidence_>0.5; }
private:
double confidence_;
CompareOptionalInfo compare_optional_info_;
};
online demo
Your production code would be unaffected by the debugging information. And you could in your debugging ALWAYS trace back the explanation of any given comparison result, at least if you store it:
Example:
auto result = Foo::compare (x, y)
if (result) ... // uses automatically the conversion
auto closest = std::max (Foo::compare (x, y), Foo::compare (y,z));
// here you not only know the closest match but could explain it !
vector<CompareResult> v;
... // populate the vector with 10 000 comparison results
auto r = std::max_element(v.begin(), v.end());
// you could still explain the compare info for the largest value
// if you're interested in the details of this single value
// how would you do this with option 3 or option 2 ?
Ok, for the very last one to work you'd also need a comparison operator for your additional class. But that's one line of code more (see the online demo) ;-)
Finally, it could turn out that your "optional debug info" could prove to be more useful than expected, for example to provide the user additional explanations upon request. All you need to do then, would be to remove the conditional #ifdef DEBUG surrounding the calculation of the optional info.
I would use the second option for its compatibility with debuggers.
In the debug mode, you can add an additional static member. You should take care of the linker that should not suppress it.
class Foo
{
private:
#ifndef NDEBUG
CompareOptionalInfo debug_out_compare_info_;
#endif
...
static double Compare(const Foo& foo1, const Foo& foo2,
CompareOptionalInfo* out_compare_info = nullptr);
...
};
#ifndef NDEBUG
CompareOptionalInfo Foo::debug_out_compare_info_;
#endif
In gdb, at any breakpoint, you can use:
call Foo::Compare(foo1, foo2, &Foo::debug_out_compare_info_);
print Foo::debug_out_compare_info_. ...

Calling GSL function inside a class in a shared library

I'm trying make a shared library in c++ implementing tools for Fermi gases. I'm using the GSL library to solve a function numerically and my code runs without a problem without when running as a script, but when trying to convert it to a shared library and classes I encounter problems.
I've seen similar questions:
Q1
Q2
Q3
I'm fairly new to c++-programming and cannot seem to adapt the different answers to my problem. Probably since I do not quite understand the answers.
My code is:
/* Define structure for the GSL-function: chempot_integrand */
struct chempot_integrand_params { double mu; double T; };
double
ChemicalPotential::chempot_integrand (double x, void * params){
/* Computes the integrand for the integral used to obtain the chemical potential.
*
* This is a GSL-function, which are integrated using gsl_integration_qag.
*/
// Get input parameters.
struct chempot_integrand_params * p = (struct chempot_integrand_params *) params;
double mu = p->mu;
double T = p->T;
// Initiate output parameters for GSL-function.
gsl_sf_result_e10 result;
int status = gsl_sf_exp_e10_e( ( gsl_pow_2(x) - mu ) / T , &result );
if (status != GSL_SUCCESS){
printf ("Fault in calculating exponential function.");
}
// Return (double) integrand.
return (gsl_pow_2(x) / ( 1 + result.val * gsl_sf_pow_int(10,result.e10) ));
}
/* Define structure for the GSL-function: chempot_integration */
struct chempot_integral_params { double T; };
double
ChemicalPotential::chempot_integration (double mu, double T){
/* Computes the integral used to obtain the chemical potential using the integrand: chempot_integrand.
*/
// Set input parameters for the integrand: chempot_integrand.
struct chempot_integrand_params params_integrand = { mu, T };
// Initiate the numerical integration.
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000); // Allocate memory for the numerical integration. Can be made larger if neccessary, REMEMBER to change it in the function call: gsl_integration_qag as well.
double result, error;
gsl_function F;
F.function = &ChemicalPotential::chempot_integrand;
F.params = &params_integrand;
// Upper limit for integration
double TOL = 1e-9;
double upp_lim = - T * gsl_sf_log(TOL) + 10;
gsl_integration_qag (&F, 0, upp_lim, 1e-12, 1e-12, 1000, 6, w, &result, &error);
// Free memory used for the integration.
gsl_integration_workspace_free (w);
return result;
}
and when compiling I get the error
error: cannot convert ‘double (Fermi_Gas::ChemicalPotential::*)(double, void*)’ to ‘double (*)(double, void*)’
in line
F.function = &ChemicalPotential::chempot_integrand;
It is indeed interesting that people ask this over and over again. One reason may be that the proposed solutions are not easy to understand. I for one had problems understanding and implementing them. (the solutions did not work out of the box for me, as you might expect.)
With the help of tlamadon I just figured out a solution that may be helpful here as well. Let's see what you guys think.
So just to recap, the problem is that you have a class that contains a member function on which you want to operate with something from the GSL library. Our example is useful if the GSL interface requires a
gsl_function F;
see here for a definition.
So here is the example class:
class MyClass {
private:
gsl_f_pars *p; // not necessary to have as member
public:
double obj(double x, void * pars); // objective fun
double GetSolution( void );
void setPars( gsl_f_pars * xp ) { p = xp; };
double getC( void ) ; // helper fun
};
The objective of this exercise is to be able to
initiate MyClass test,
supply it with a paramter struct (or write a corresponding constructor), and
call test.GetSolution() on it, which should return whatever the GSL function was used for (the minimum of obj, a root, the integral or whatever)
The trick is now to put have an element in the parameter struct gsl_f_pars which is a pointer to MyClass. Here's the struct:
struct gsl_f_pars {
double a;
double b;
double c;
MyClass * pt_MyClass;
};
The final piece is to provide a wrapper that will be called inside MyClass::GetSolution() (the wrapper is a stand in for the member function MyClass::obj, which we cannot just point to with &obj inside the class). This wrapper will take the parameter struct, dereference pt_MyClass and evaluate pt_MyClass's member obj:
// Wrapper that points to member function
// Trick: MyClass is an element of the gsl_f_pars struct
// so we can tease the value of the objective function out
// of there.
double gslClassWrapper(double x, void * pp) {
gsl_f_pars *p = (gsl_f_pars *)pp;
return p->pt_MyClass->obj(x,p);
}
The full example is a bit too long to post here, so I put up a gist. It's a header file and a cpp file, it should be working wherever you have GSL. Compile and run with
g++ MyClass.cpp -lgsl -o test
./test
This is a duplicate question. See Q1 or Q2 for example. Your problem is the following: you cannot convert pointers to member functions to free function pointers. To solve your problem, there are two options. You can define your member function as static (which is bad in 90% of the case because the member function will not be attached to any instantiation of your class and that is why you can convert it to a free function) or you can use the wrapper you linked that will use a static member functions under the hood to make your code compatible with gsl without the need of declaring your particular member function static.
EDIT #Florian Oswald. Basically your entire solution can be implemented in 2 lines using std::bind the wrapper I cited before
gsl_function_pp Fp( std::bind(&Class::member_function, &(*this), std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);
In practice is this is just 1 extra line from a pure C code!
As I stated in a comment, wrapping every member function that you want to integrate using an extra global struct and an extra global function is cumbersome and pollute your code with a lot of extra functions/struct that are completely unnecessary. Why use c++ if we refuse to use the features that make C++ powerful and useful (in comparison to C)?
Another classical Example: if you want to pass a LOT of parameters, use lambda functions (no extra struct or global functions) !!!
To be more precise: Imagine you have 2 parameters (doubles) .
//Declare them (locally) here
double a1 = ...;
double a2 = ...;
// Declare a lambda function that capture all of them by value or reference
// no need to write another struct with these 2 parameters + class pointer
auto ptr = [&](double x)->double {/.../};
// Cast to GSL in 3 lines using the wrapper
std::function<double(double)> F1(ptr);
gsl_function_pp F2(F1);
gsl_function *F = static_cast<gsl_function*>(&F2);
No extra global struct of global functions and no extra wrapper (the same wrapper that solved the problem of integrating member function also solved the problem of integrating a lambda expression). Of course this is a matter of style in the end, but in the absence of these nice features that allow the use of C libraries without code bloat, I would never leave C.

Initializing and assigning values,from pass by reference

Okay, this is just a minor caveat. I am currently working with the lovely ArcSDK from ESRI. Now to get a value from any of their functions, you basically have to pass the variable, you want to assign the value to.
E.g.:
long output_width;
IRasterProps->get_Width(&output_width);
Its such a minor thing, but when you have to pick out around 30 different pieces of data from their miscellaneous functions, it really starts to get annoying.
So what i was wondering is it possible to somehow by the magic of STL or C++ change this into:
long output_width = IRasterProps->get_Width(<something magical>);
All of the functions return void, otherwise the off chance some of them might return a HRESULT, which i can safely ignore. Any ideas?
***EDIT****
Heres the final result i got which works :)!!!!!
A magic(P p, R (__stdcall T::*f)(A *)) {
A a;
((*p).*f)(&a);
return a;
}
I know I've already answered, but here's another way. It's better in that it's faster (no boost::function overhead) and avoids the binders (since people seem to have an aversion to them), but is worse in that it's much less general (since it only works for one-argument member functions).
template <typename P, typename T, typename A>
A magic(P p, void (T::*f)(A &)) {
A a;
((*p).*f)(a);
return a;
}
Which you'd call like this:
long output_width = magic(raster_props_object, &IRasterProps::get_Width);
Or, if you happen to be using GCC, we can use some more tricks:
#define MORE_MAGIC(p,f) ({ \
typedef __typeof(*(p)) big_ugly_identifier; \
magic((p),(&big_ugly_identifier::f)); \
})
Which will let us do this:
long output_width = MORE_MAGIC(raster_props_object, get_Width);
(Bonus points if the naming conventions made you think of a PDP-10.)
EDIT: Updated to take any pointer-like type, so it will now work with shared_ptr, iterators, and hopefully _com_ptr.
EDIT: Oops, they're pointers, not references. Here's a version (or overload) that deals with that, and allows -- by ignoring -- arbitrarily-typed return values.
template <typename P, typename T, typename A, typename R>
A magic(P p, R (T::*f)(A *)) {
A a;
((*p).*f)(&a);
return a;
}
This is not quite what you specified because you need to wrap get() around the method, but it works:
template<class T, class S>
T get(S fun(T&)) {
T result;
fun(result);
return result;
}
void foo(int& x) {
x = 5;
}
bool bar(char& x) {
x = 'c';
return false;
}
int main() {
int x = get(foo);
char y = get(bar);
return 0;
}
Can you derive from IRasterProps? Being that the case you can construct your own interface to it.
EDIT: Following on the concept you can probably also apply the Adapter design pattern (or even a Facade if you wish to apply a common interface to several like-minded classes of the SDK).
Looks like a COM object to me.
Visual C++ supports an #import directive to import the type library, and create high-legel wrappers. So you either end up with
width = ptr->GetWidth();
or - even better -
width = ptr->Width;
If a function fails, the HRESULT returned will be transformed into an _com_error exception.
I've used that successfully on many OS and 3rd party COM objects, makes them much easier to use.
Note that you control the wrapper generation through options, the first thing I do is usually adding a rename_namespace or no_namespace, because otherwise the symbold end up in a namespace depending on the typelib name, which is usually ugly.
also, unless you use named_guids option, you might needto change CLSID_xxx and IID_xxx constants to __uuidof(xxx).
EDIT: In retrospect, I'm not sure this one will actually work, since I don't think the template arguments will deduce. Buyer Beware.
Sure! What you need is something to which you can pass a function that will call it and return you the outputted value.
Here's the easy, if less efficient way:
template <typename T>
T magic(boost::function<void(T&)> f) {
T x;
f(x);
return x;
}
Which you'd then call like this using boost::lambda:
long output_width = magic(raster_props_object->*&IRasterProps::get_Width);
Or like this, using boost::bind:
long output_width = magic(bind(&IRasterProps::get_Width, raster_props_object, _1));
You can get rid of boost::function, but that's uglier. Probably worth it, though.
Don't think this is possible. Assigning void to a long should be an error in any case.
Remember, it's probably more performant to pass-by-reference than to return a large object. (won't really make a difference with long's though)
Compiling this:
void foo(long &a) {
}
int main(void) {
long a=0;
a = foo(a);
return 0;
}
gives this error:
g++ x.cc
x.cc: In function ‘int main()’:
x.cc:9: error: void value not ignored as it ought to be
I'm not aware of something insane you could do, precisely like you're asking, and if there was some insane hackery that did work on some peculiar platform I'm pretty sure in a code-review I'd hate it.
It may may more sense to either...
define some trivial inline function wrappers around the APIs you care about
make a specialized class descend from IRasterProps (or whatever) that provides the appropriate accessor methods.
Either of those will impact maintenance time of the code but would safely and cleanly give you the call syntax you are looking for.