我如何避免使用依赖于参数的查找明确专门化模板化功能
How Can I Avoid Explicitly Specializing Templatized Functions With Argument Dependent Lookup
所以我已经写了一个答案,该答案使用模板化函数选择对象类型。
我已经定义了类型:
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)建议使用依赖参数查找(ADL)来避免"明确的专业模板功能"。我只是不确定他的意思,所以我认为我会打开一个新问题,以便他或某人可以在答案中进一步解释。
与这些行相符的东西。
请注意,我现在可以添加一个新的点类型(或设置类型),而无需更改多个功能中的逻辑。我要做的就是为新类型提供operator>>
和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());
}
};
在下面的示例中,您不需要指定要阅读的点的类型。相反,编译器可以通过将您传递到的参数中弄清楚功能。(注意:此代码块假定set
,dataFile
和data_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
}
如果您想要模板参数扣除,则必须从某些东西中推断出来。例如,您可以从其参数中得出函数模板参数。例如,您可以将功能更改为:
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);
相关文章:
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 多态性和功能结合
- 带内存和隔离功能的SQLite
- 在CMakeLists.txt的安装功能中使用.cmake文件有什么用
- 类模板的成员功能的定义在单独的TU中完全专业化
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在C++中获得"静态纯虚拟"功能?
- 是否可以对零模板参数进行模板专门化
- 两个文件使用彼此的功能-如何解决
- 我应该实现右值推送功能吗?我应该使用std::move吗
- QML按钮点击功能执行顺序
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 如何在同一个模板功能上专门化几种类型?
- 根据成员容器的尺寸,专门化成员功能
- 如何专门化模板的模板功能
- 我如何避免使用依赖于参数的查找明确专门化模板化功能
- C++专门化成员功能
- 在不丢失功能的情况下通过重载来专门化类
- 此功能模板是否专门化
- 如何使用模板类型专门化模板功能