【问题标题】:How Can I Avoid Explicitly Specializing Templatized Functions With Argument Dependent Lookup如何避免使用参数相关查找显式特化模板化函数
【发布时间】:2016-12-14 03:40:16
【问题描述】:

所以I've written an answer 使用模板化函数来选择对象类型。

我已经定义了类型:

struct pt {
    double t;
    double e;
    double c_vis;
    double c_invis;
};

struct pt_weighted : pt {
    double sigma;
};

我的模板化函数如下所示:

template <typename T>
void foo() {
    for(T point; dataFile >> point;) {
        set.curve.push_back(point); // store point

        data_numPoints++; // collect some stats
        set.curveAvg += point.e;            
    }
}

鉴于minimizator_weighted 决定在运行时使用哪种类型,我调用foo 时使用:

minimizator_weighted ? foo<data_set::pt_weighted>() : foo<data_set::pt>();

Richard Hodges is suggesting 使用Argument Dependent Lookup (ADL) 来避免“显式专用模板函数”。我只是不确定他的意思,所以我想我会提出一个新问题,以便他或其他人可以在答案中进一步解释。

【问题讨论】:

    标签: c++ runtime specialization argument-dependent-lookup function-templates


    【解决方案1】:

    类似的东西。

    请注意,我现在可以添加新的点类型(或集合类型),而无需更改多个函数中的逻辑。我所要做的就是为新类型提供operator&gt;&gt;do_something 的ADL 重载。

    所以我的核心逻辑现在与每个集合类型/点类型的实现细节分开了。如果我想在其他坐标系统中使用相同的代码点,我需要更改的代码更少(在实际项目中)。

    #include <iostream>
    #include <vector>
    
    struct pt {
        double t;
        double e;
        double c_vis;
        double c_invis;
    };
    std::istream& operator>>(std::istream& is, pt& p)
    {
      p.c_vis = 0;
      p.c_invis = 0;
      return is >> p.t >> p.e;
    }
    
    struct pt_weighted : pt {
        double sigma;
    };
    
    std::istream& operator>>(std::istream& is, pt_weighted& p)
    {
        auto sigma_correction = [](double& sigma) {
          // whatever this is supposed to do;
        };
      is >> static_cast<pt&>(p) >> p.sigma;
      sigma_correction(p.e);
      return is;
    }
    
    
    template<class Point> struct set
    {
      using point_type = Point;   // the type name point_type is now part of the set's type interface, so I can use it in dependent code.
      std::vector<point_type> points;
    };
    
    using pt_set = set<pt>;
    using pt_weighted_set = set<pt_weighted>;
    
    
    //
    // one implementation of read logic, for all set types.
    //
    template<class SetType>
    void read_set(std::istream& is, SetType& target)
    {
      while(is) {
        // using the type protocol here
        auto point = typename SetType::point_type(); // or target.makePoint() ?
        is >> point;
        target.points.push_back(std::move(point));    
      }
    }
    
    extern void do_something(pt_set&);
    extern void do_something(pt_weighted_set&);
    
    void operation(std::istream& is)
    {
      extern bool useSigma();
    
      // even these lines now no longer need to be repeated
      auto perform = [](auto&& myset) {
        read_set(is, myset);
        do_something(myset);
      };
    
      if (useSigma())
      {
        perform(pt_weighted_set());
      }
    //else if (someOtherCondition()) {
    //  perform(someOtherSetType());
    //}
      else {
        perform(pt_set());
      }
    };
    

    【讨论】:

      【解决方案2】:

      在下面的示例中,您不需要指定要读取的点的类型。相反,编译器可以通过您传递给函数的参数来确定这一点。 (注意:此代码块假定 setdataFiledata_numPoints 在函数内是可访问和可变的。)

      template<class T>
      void foo(T point) {
          while (dataFile >> point) {
              set.curve.push_back(point);
              data_numPoints++;
              set.curveAvg += point.e;
          }
      }
      

      现在,要调用它,您只需传入您关心的类型的实例。

      void bar() {
          foo(data_set::pt()); // builds unweighted data set
          foo(data_set::pt_weighted()); // builds weighted data set
      }
      

      【讨论】:

        【解决方案3】:

        如果你想要模板参数推导,你必须从一些东西中推导出来。例如,您可以从参数中推断出函数模板参数。例如,您可以将函数更改为:

        template <typename T>
        void foo(T p) {
            for(T point = p; dataFile >> point;) {
                set.curve.push_back(point); // store point
        
                data_numPoints++; // collect some stats
                set.curveAvg += point.e;            
            }
        }
        

        然后当你调用你的函数时,你可以这样推断:

        data_set::pt_weighted ptw;
        data_set::pt pt;
        
        minimizator_weighted ? foo(ptw) : foo(pt);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-11-27
          • 2013-11-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多