模板函数,其中一个参数需要专门化,而另一个不需要



我在图中工作,我想在有向图中进行一些搜索,在一种情况下,边像往常一样指向,在另一种情况中,边在相反的方向。边缘有时间横向移动。这个时间不一定是固定值或类的成员,它们可以具有不同的持续时间类型(std::chrono::secondsstd::chrono::milliseconds…(。对于这两种情况中的每一种,我都需要一个函数来添加时间。这个函数在这两种情况下是不同的,对于每种情况,它也应该是一个模板,因为持续时间类型可能不同。

我的想法是做以下事情:

class ForwardEdge;
class ReverseEdge;
template<typename DurationType>
std::chrono::time_point time_sum<ForwardEdge>(std::chrono::time_point tp, DurationType inc) {
return tp + inc;
}
template<typename DurationType>
std::chrono::time_point time_sum<ReverseEdge>(std::chrono::time_point tp, DurationType inc) {
return tp - inc;
}

做这件事的正确方法是什么?

问题是您可以对模板函数进行部分专门化。

如果您接受一个基于struct的解决方案,其中包含(static?(模板函数,则可以专门化struct

我的意思是。。。如下

template <typename>
struct struct_sum;
template <>
struct struct_sum<ForwardEdge>
{
template <typename DurationType>
static std::chrono::time_point func(std::chrono::time_point tp,
DurationType inc)
{ return tp + inc; }
};

template <>
struct struct_sum<ReverseEdge>
{
template <typename DurationType>
static std::chrono::time_point func(std::chrono::time_point tp,
DurationType inc)
{ return tp - inc; }
};

你可以用这种方式

struct_sum<ForwardEdge>::func(tp, inc);

在专门化模板之前,首先必须介绍它:

template<typename Edge, typename DurationType>
std::chrono::time_point time_sum(std::chrono::time_point tp, DurationType inc);
template<typename DurationType>
std::chrono::time_point time_sum<ForwardEdge, DurationType>( /*...*/ )
//                                   ^^^            ^^^
// you still need to specify ALL template parameters!

Solely:这是部分专业化!不允许对函数进行部分专门化,只允许对类型进行

所以我们需要一个辅助类:

template<typename Edge, typename DurationType>
struct TimeSum;
template<typename DurationType>
struct TimeSum<ForwardEdge, DurationType>
{
std::chrono::time_point operator()(std::chrono::time_point tp, DurationType d)
{
return tp + d;
}
};
template<typename DurationType>
struct TimeSum<ReverseEdge>
{
std::chrono::time_point operator()(std::chrono::time_point tp, DurationType d)
{
return tp - d;
}
};

现在我们可以在一个完全非专业化的功能中使用这些类型:

template<typename Edge, typename DurationType>
std::chrono::time_point time_sum(std::chrono::time_point tp, DurationType inc)
{
return TimeSum<Edge, DurationType>()(tp, inc);
//              ^^^
// selects appropriate partial specialisation
}

到目前为止,我们只得到了这两个专业化,任何其他模板实例化都没有定义。一种变体可能是:

template<typename Edge, typename DurationType>
{
std::chrono::time_point operator()(std::chrono::time_point tp, DurationType d)
{
return tp + d;
}
};
// and the specialisation for ReverseEdge from above

在这种情况下,您有一个通用模板,适用于专业化未涵盖的任何类型(包括ForwardEdge(和特定于ReverseEdge的专业化。考虑到类型的名称(TimeSum(,这可能是更合适的变体。

但是,由于没有边函数参数,您需要手动指定模板参数。如果确实有可用的边缘,过载可能是更好的选择:

template<typename DurationType>
std::chrono::time_point time_sum
(
ForwardEdge const&, // <--
std::chrono::time_point tp, DurationType inc
);
template<typename DurationType>
std::chrono::time_point time_sum
(
ReverseEdge const&, // <--
std::chrono::time_point tp, DurationType inc
);

另一种选择是在每个类中都有成员函数(如果这些函数共享一个公共基,则可能是虚拟的(。

最新更新