如何避免使用依赖于参数的查找来明确地专门化模板化函数 [英] How Can I Avoid Explicitly Specializing Templatized Functions With Argument Dependent Lookup

查看:102
本文介绍了如何避免使用依赖于参数的查找来明确地专门化模板化函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我写了一个答案,该答案使用模板化函数来选择对象类型。

So I've written an answer which uses a templatized function to select object type.

我定义了以下类型:

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

考虑到决定在运行时使用哪种类型,我通过以下方式调用 foo

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

Richard Hodges建议使用使用依赖于参数的查询(ADL)可以避免显式专用的模板函数。我只是不确定他的意思,所以我想我要打开一个新问题,以便他或某人可以在答案中进一步解释。

Richard Hodges is suggesting using Argument Dependent Lookup (ADL) to avoid "explicitly specialized template functions". I'm just not sure what he means so I thought I'd open a new question so he or someone could explain further in an answer.

推荐答案

遵循这些原则。

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

Note that I can now add a new point type (or set type) without changing the logic in more than one function. All I have to do is provide ADL overloads of operator>> and do_something for the new types.

现在,我的核心逻辑与每种设置类型/点类型的实现细节分开了。如果我想在其他坐标系统中使用相同的代码点,则在真实项目中更改的代码较少。

So my core logic is now separated from the implementation details of each set type/point type. If I want to use the same code points in some other co-ordinate system I have less code to change (in a real project).

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

这篇关于如何避免使用依赖于参数的查找来明确地专门化模板化函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆