如何重构具有相同行的函数,只有一个函数调用不同?

时间:2016-09-12 02:29:27

标签: c++ templates c++03

请考虑以下代码段

template <typename T>
void MyDynamicArray<T>::resize(size_t count)
{
    size_t prev_count = Count();
    if(count < prev_count)
    {
       DestroyMemory(prev_count, count);
    }
    else if(count > prev_count)
    {
      Reserve(count);

      for(size_t i=prev_count; i<count; i++)
      {
         // change in function call
         m_block.DefaultConstruct();
      }
    }
  }

这是同一功能的重载

  template<typename T>
  void MyDynamicArray<T>::resize(const T &object, size_t count)
  {
     size_t prev_count = Count();
    if(count < prev_count)
    {
       DestroyMemory(prev_count, count);
    }
    else if(count > prev_count)
    {
      Reserve(count);

      for(size_t i=prev_count; i<count; i++)
      {
         // change in function call
         m_block.CopyConstruct(object);
      }
    }
  }

一种方法,我认为重构resize函数是提供const T * pObject作为默认参数。并检查是否提供,然后调用CopyConstruct。

另一种方法是提供一个调整大小调整另一个调整大小的包装器。

最好的方法是什么?

2 个答案:

答案 0 :(得分:0)

在任何可能的情况下,都没有普遍适用的“最佳方法”。例如,如果代码膨胀不是一个问题,你可以有一对外观到一个公共函数,将一个适当的lambda传递给公共函数:

template <typename T>
void MyDynamicArray<T>::resize(size_t count)
{
    resize_common(count, [] { m_block.DefaultConstruct(); });
}

template <typename T>
void MyDynamicArray<T>::resize(const T &object, size_t count)
{
    resize_common(count, [&] { m_block.CopyConstruct(object); });
}

template <typename T, typename lambda_t>
void MyDynamicArray<T>::resize_common(size_t count, lambda_t &&lambda)
{
    size_t prev_count = Count();
    if(count < prev_count)
    {
       DestroyMemory(prev_count, count);
    }
    else if(count > prev_count)
    {
      Reserve(count);

      for(size_t i=prev_count; i<count; i++)
      {
         lambda();
      }
    }
}

如果代码膨胀是一个问题,那么你自己作为一种可能性提供的变体:

template <typename T>
void MyDynamicArray<T>::resize(size_t count)
{
    resize_common(count, null);
}

template <typename T>
void MyDynamicArray<T>::resize(const T &object, size_t count)
{
    resize_common(count, &object);
}

template <typename T>
void MyDynamicArray<T>::resize_common(size_t count, const T *object)
{
    size_t prev_count = Count();
    if(count < prev_count)
    {
       DestroyMemory(prev_count, count);
    }
    else if(count > prev_count)
    {
      Reserve(count);

      for(size_t i=prev_count; i<count; i++)
      {
         if (object)
              m_block.CopyConstruct(*object);
         else
              m_block.DefaultConstruct();
      }
    }
}

我确信人们可以想到一些相同的变体。最重要的是回答“哪一个是最好的”,必须考虑到您的个人要求,考虑每个替代实施满足要求的程度,并选择其中一个。代码膨胀应该最小化吗?整体表现是个问题吗?等...

答案 1 :(得分:0)

一种解决方案是创建一个虚拟对象,您可以将其传递给新函数a以指示它是默认构造:

m_block.Construct()

我们在最后使用的是:

struct default_construct_t { };

现在您只需为template <typename T> void MyDynamicArray<T>::resize(size_t count) { resize(count, default_construct_t()); } template <typename T, typename Obj> void MyDynamicArray<T>::resize(size_t count, Obj const& obj) { size_t prev_count = Count(); if(count < prev_count) { DestroyMemory(prev_count, count); } else if(count > prev_count) { Reserve(count); for(size_t i=prev_count; i<count; i++) { // change in function call m_block.Construct(obj); } } } Construct(default_construct_t )提供重载。