Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing and assigning values,from pass by reference

Tags:

c++

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;
}
like image 263
UberJumper Avatar asked Dec 17 '22 06:12

UberJumper


1 Answers

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;
}
like image 60
me22 Avatar answered Jan 01 '23 23:01

me22