How to write a template function that can handle function calls of an object or pointer?

I would like to write a template function that can call a function call for all elements of the container. It can be assumed that the function name is always the same. However, it is not known whether the container contains objects or pointers. those. whether to cancel the link.

template< typename TContainer > void ProcessKeyedContainer( TContainer &keyedContainer ) { for ( auto it = keyedContainer.begin(); it != keyedContainer.end(); ++it ) { // do some random stuff here. // ... auto value = it->second; value.Process(); // or value->Process() if the container has pointers } } ... std::map< int, CMyObject > containerOfObjects; containerOfObjects[0] = CMyObject(); std::map< int, CMyObject* > containerOfPointers; containerOfPointers[0] = new CMyObject(); // I would like both calls to look near identical ProcessKeyedContainer( containerOfObjects ); ProcessKeyedContainer( containerOfPointers ); 

Is there a neat way to make a Process call inside a ProcessKeyedContainer without putting a burden on the caller (i.e., the caller does not need to use it one way for pointers and another way for objects), and without having to duplicate too much code?

+4
source share
1 answer

An overloaded function template is a savior:

 template<typename T> void invoke(T * obj) //when object is pointer { obj->Process(); } template<typename T> void invoke(T & obj) //when object is non-pointer { obj.Process(); } 

then use it like:

 auto value = it->second; invoke(value); //correct invoke() will be selected by the compiler! 

But this is not good enough, since you can do something else with value in the rest of the function you wrote. Therefore, if you follow the approach described above, code duplication will occur, since both invoke() will have almost similar code.

So, here is one improvement: instead of using invoke() , turn the pointer into a link so that you can use it evenly in your function.

 template<typename T> T& ensure_ref(T * obj) //when object is pointer { return *obj; //return the dereferenced object } template<typename T> T& ensure_ref(T & obj) //when object is non-pointer { return obj; //simply return it } 

And use it like:

 auto & value = ensure_ref(it->second); //call ensure_ref to ensure reference! value.Process(); //value is gauranteed to be NOT pointer! //you might want to do this also! value.xyz = abc; 

Hope this helps!

+6
source

Source: https://habr.com/ru/post/1495369/


All Articles