如何编写可以处理对象或指针函数调用的模板函数?

Kin*_*ead 4 c++ templates

我希望能够编写一个模板函数,可以调用容器的所有元素上的函数调用.我们可以假设函数名称始终相同.然而,未知的是容器是否保持物体或指针.即,我是否应该去引用.

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 );
Run Code Online (Sandbox Code Playgroud)

有没有一种巧妙的方法可以在ProcessKeyedContainer中进行Process调用,而不会给调用者带来负担(即调用者不必知道以一种方式使用它来获取指针而另一种方式使用对象),并且没有不得不复制太多代码?

Naw*_*waz 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();
}
Run Code Online (Sandbox Code Playgroud)

然后用它作为:

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

但这还不够好,因为您可能希望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
}
Run Code Online (Sandbox Code Playgroud)

并将其用作:

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; 
Run Code Online (Sandbox Code Playgroud)

希望有所帮助!