Initialization and assignment of values, from passing by reference

Well, this is just a small caveat. I am currently working with the excellent ESRI ArcSDK. Now, to get a value from any of their functions, you basically need to pass a variable, you want to assign a value.

eg:.

long output_width; IRasterProps->get_Width(&output_width); 

This is such a minor thing, but when you have to choose about 30 different pieces of data from its different functions, it really starts to get annoying.

So I was wondering if it is somehow possible by the magic of STL or C ++ to change this to:

 long output_width = IRasterProps->get_Width(<something magical>); 

All functions return void, otherwise the probability that some of them can return HRESULT, I can safely ignore. Any ideas?

*** EDIT ****

Here is the final result that I got, which works:) !!!!!

 A magic(P p, R (__stdcall T::*f)(A *)) { A a; ((*p).*f)(&a); return a; } 
+4
source share
7 answers

I know that I already answered, but here it’s different. The better thing is that it is faster (without boost :: function overhead) and avoids binders (since people seem to have an aversion to them), but worse is that it is much less general (since it only works for functions with one argument).

 template <typename P, typename T, typename A> A magic(P p, void (T::*f)(A &)) { A a; ((*p).*f)(a); return a; } 

What would you call so:

 long output_width = magic(raster_props_object, &IRasterProps::get_Width); 

Or, if you use GCC, we can use some more tricks:

 #define MORE_MAGIC(p,f) ({ \ typedef __typeof(*(p)) big_ugly_identifier; \ magic((p),(&big_ugly_identifier::f)); \ }) 

What will allow us to do this:

 long output_width = MORE_MAGIC(raster_props_object, get_Width); 

(Reward points if naming conventions made you think of PDP-10.)

EDIT : updated to use any type of pointer, so now it will work with shared_ptr, iterators and hopefully _com_ptr.

EDIT . Unfortunately, these are pointers, not links. Here's the version (or overload) that is relevant to this, and allows - 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; } 
+7
source

This is not exactly what you specified because you need to wrap the get () method 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; } 
+2
source

EDIT . Looking back, I’m not sure if this will really work, since I don’t think the template arguments will be output. Buyer Beware.

Sure! What you need is what you can pass the function to, which will call it, and return you the displayed value.

Here is a simple, if less effective way:

 template <typename T> T magic(boost::function<void(T&)> f) { T x; f(x); return x; } 

What would you then call like this using boost :: lambda:

 long output_width = magic(raster_props_object->*&IRasterProps::get_Width); 

Or, for example, using boost :: bind:

 long output_width = magic(bind(&IRasterProps::get_Width, raster_props_object, _1)); 

You can get rid of boost :: function, but it's uglier. Probably worth it.

+1
source

Can you get from IRasterProps? In this case, you can create your own interface for yourself.

EDIT. Following the concept, you can probably also apply an adapter design pattern (or even Facade if you want to apply a common interface to several classes with the same attention to the SDK).

+1
source

Looks like a COM object to me. Visual C ++ supports the # import directive to import type libraries and create high-level wrappers. So you either end up with

 width = ptr->GetWidth(); 

or - even better -

 width = ptr->Width; 

If the function does not work, the returned HRESULT is thrown into the _com_error exception.

I have successfully used this for many OS and third-party COM objects, which makes them much easier to use.

Note that you control the generation of the wrapper via parameters, the first thing I do is usually add rename_namespace or no_namespace , because otherwise the character will end up in the namespace depending on the typelib name, which is usually ugly.

if you are not using the named_guids parameter, you may need to change the constants CLSID_xxx and IID_xxx to __uuidof(xxx) .

+1
source

Do not think it is possible. Assigning a void to the length should be a mistake in any case.

Remember that it is probably more efficient for passing by reference than for returning a large object. (in fact, this will not affect for a long time)

Compilation:

 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 
0
source

I don’t know about something crazy that you could do, just like you ask, and if there was some kind of crazy hacker who worked on some kind of platform, I’m quite sure of revising the code that I he would hate.

Maybe this might make more sense ...

  • define some trivial built-in wrappers of functions around the API that you like

  • make a specialized class for transition from IRasterProps (or something else) that provides appropriate access methods.

Any of them will affect the code maintenance time, but it will safely and cleanly give you the syntax of the call you are looking for.

0
source

All Articles