【问题标题】:How to convert three functions to one generic function?如何将三个函数转换为一个通用函数?
【发布时间】:2014-06-21 11:01:37
【问题描述】:

我在下面的示例中有三个 getColors 函数。

问题:如何将三个 getcolors 函数转换为一个泛型函数?

struct EcvColorMap{
    vector<Scalar> getColors(){
        vector<Scalar> result;
        //....
        return result;
    }
};
struct Scalar{
   int val[3];
};

    vector<Scalar> getColors(vector<Scalar> colors){
        return colors;
    }
    vector<Scalar> getColors(Scalar color){
        return{ color };
    }
    vector<Scalar> getColors(EcvColorMap color_map){
        return color_map.getColors();
    }

【问题讨论】:

  • 您可以制作一个通用的并根据需要对其进行专门化,但它们完全不同,您最好只拥有三个功能。
  • 您为什么要这样做?拥有这三个重载看起来是正确的设计。

标签: c++ templates generics


【解决方案1】:

问题是:函数的主体是不同的,如果您尝试制作一个通用的,而让其他的部分专业化和完全专业化,就像

template<typename T> vector<Scalar> getColors(T colors) {
    return {colors};
}

//template<typename T> vector<Scalar> getColors(vector<T> colors) { // Not really necessary - see list initialization
//  return colors;
//}

template<> vector<Scalar> getColors<EcvColorMap>(EcvColorMap colors) {
    return colors.getColors();
}

您仍然必须为三个不同的模板编写代码而毫无收获(编译时优势或代码重用在哪里?)。

我的个人建议:不要仅仅因为它很酷就使用模板,在实际需要时使用它们。从庞大的软件角度来看,这是至关重要的。你发布的设计对我来说很有意义。

【讨论】:

  • getColors(vector&lt;T&gt; colors) 是不必要的,getColors(T colors) 处理从vector&lt;T&gt; 构造vector&lt;Scalar&gt;
  • @CaptainObvlious 没错,我需要更好地学习C++11,初始化列表也可以调用拷贝构造函数。
【解决方案2】:

你不需要转换这些函数,这很清楚。

您的三个函数具有不同的主体,因此您不能将它们放在一个模板函数中。您可以将它们替换为模板函数,并对这些类型进行专门化,但这只会使其复杂化。

【讨论】:

    【解决方案3】:

    正如 Marco 的回答所指出的,在这种情况下,您必须权衡使用模板的利弊。

    话虽如此,您可以检查一个典型的方法,使用特征;当您想要抽象出可能以不同方式发生的事情时,通常会这样做。所以你可以像这样调度实际的 getter

    template<typename T>
    vector<Scalar> getColors(T colors)
    {
        return getter<T>::get(colors); 
    }
    

    然后,您将为每个实体构建一些特征

    template<typename T>
    struct getter; // types not specified in your traits system will not work
    
    template<>
    struct getter<vector<Scalar>> {
        static vector<Scalar> get(vector<Scalar> colors) { 
            return colors; 
        }
    };
    
    template<>
    struct getter<Scalar> {
        static vector<Scalar> get(Scalar color) { 
            return { color }; 
        }
    };
    
    template<>
    struct getter<EcvColorMap> {
        static vector<Scalar> get(EcvColorMap color) { 
            return color_map.getColors(); 
        }
    };
    

    那里没有魔法,您仍然需要手动编写所有代码。 唯一有用的情况是你必须在更多地方使用 getter,这样你就可以一直这样写:

    template<typename T>
    void FunctionN(T arg)
    {
        auto val = getter<T>::get(arg); 
        // do stuff like printing etc
    }
    

    因此,N 越大,您从抽象出 get 操作中获得的收益就越多。类似地,set 操作可以被划分等等等等..

    【讨论】:

      【解决方案4】:

      前两个函数使用Scalarvector&lt;Scalar&gt; 类型,它们都可以用来构造vector&lt;Scalar&gt;。您可以将它们简化为一个支持任何可转换为Scalarvector&lt;Scalar&gt; 的类型的函数。

      template <class T>
      std::vector<Scalar> getColors(const T& data)
      {
          return { data };
      }
      
      // Overloads do not need to be a template.
      std::vector<Scalar> getColors(const EcvColorMap& data)
      {
          return { data.getColors() };
      }
      

      要消除最终的getColors 函数(如果有意义),您可以在EcvColorMap 中提供显式转换运算符。这将允许将EcvColorMap 的实例传递给上面显示的getColors 版本..

      struct EcvColorMap
      {
          explicit operator std::vector<Scalar>() const
          {
              std::vector<Scalar> result;
              //....
              return result;
          }
      };
      

      通过上述两项更改,您现在可以针对问题中列出的所有类型调用getColors

      std::vector<Scalar> colors;
      Scalar color;
      EcvColorMap colormap;
      
      getColors(color);
      getColors(colors);
      getColors(colormap);
      

      如果提供转换运算符有意义,您可以通过构造和赋值消除getColors 函数。

      std::vector<Scalar> colors;
      Scalar color;
      
      // Construct
      std::vector<Scalar> new_colors1{color};
      std::vector<Scalar> new_colors2{colors};
      
      // Assign.
      std::vector<Scalar> new_colors;
      new_colors = colors;
      new_colors = { color };
      new_colors = colormap.getColors();
      

      【讨论】:

        猜你喜欢
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-26
        • 1970-01-01
        • 2017-07-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多