4

I would like to be able to write a template function that can invoke a function call on all elements of a container. We can assume that the function name is always the same. However what isn't known is whether the container is holding objects or pointers. ie, whether I should de-reference.

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 be able to make the Process call inside ProcessKeyedContainer, without putting a burden on the caller ( ie the caller doesn't have to know to use it in one way for pointers and another way for objects ), and without having to duplicate too much code ?

4

1 回答 1

6

重载的函数模板是救星:

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();
}

然后将其用作:

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

但这还不够好,因为您可能还想在value您编写的其余函数中做其他事情。因此,如果您遵循上述方法,则会出现代码重复,因为两者invoke()的代码几乎相似。

所以这里有一个改进:不是使用invoke(),而是将指针转换为引用,以便您可以在函数中统一使用它。

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
}

并将其用作:

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; 

希望有帮助!

于 2013-08-05T17:24:58.483 回答