接受子类的模板作为对象的模板

时间:2016-06-19 04:35:23

标签: c++ templates c++11

在下面的示例中,使用std :: chrono库,我正在寻找一种方法来接受基本计时器的持续时间类型。

template <std::chrono::duration D> //Accept either std::chrono::minute, second, etc...
class myTimer{


}

但是,由于持续时间与模板关键字的条件不匹配,因此无效。

template <class T>
class myTimer{

   //I could do a static cast, but Duration is only a template used by the children, not an actual class per say. 

}

所以我的问题归结为,对于更少的代码和更好的可用性,最佳解决方案是什么?我觉得像模板中一个不知名的孩子的静态演员阵容不会很好,但我可能完全错了。

1 个答案:

答案 0 :(得分:0)

你在这里有很多选择,从简单而不是非常灵活,到非常灵活但更多的工作。

最简单的方法是只存储nanoseconds,而不是模板myTimer

class myTimer
{
    std::chrono::nanoseconds time_;
    ...
};

您的构造函数可以使用nanoseconds。所有“内置”计时单元都将隐式转换为nanoseconds

myTimer t{3min};  // ok, 180'000'000'000ns

此处唯一的缺点是,每个 duration都不会隐式转换为nanoseconds。也许你希望你的客户能够使用皮秒,1 / 60s单位或浮点持续时间,或者这里的意图(很难说)是控制计时器内存储的精度(不是真的必要,但你永远不知道)。 然后您可能会转向模板化解决方案:

is_duration模板开始并不是一个糟糕的起点。即使你最终没有将它用于这个项目,它也可能在另一个项目中得心应用:

template <class T>
struct is_duration
    : public std::false_type
    {};

template <class Rep, class Period>
struct is_duration<std::chrono::duration<Rep, Period>>
    : public std::true_type
    {};

现在你可以说is_duration<T>{}这是一个编译时bool,它将回答true为false。您可以像这样使用它(例如):

template <class D,
          class = std::enable_if_t<is_duration<D>{}>>
class myTimer
{
    D time_;
};

除了std::chrono::duration之外,这将使实例化无法编译。

您也可以采用不需要is_duration的方法:

template <class D> class myTimer;

template <class Rep, class Period>
class myTimer<std::chrono::duration<Rep, Period>>
{
};

如果有兴趣探索此路线,请尝试两种方式并确定您最喜欢的错误消息。

不要忘记:对您来说最好的解决方案可能是最简单的方法:只需使用nanoseconds并使其具体化。