如何测试是否存在模板函数专门化

lrl*_*eon 5 c++ templates template-meta-programming c++11 c++14

我正在管理单位转换.告诉我们,我达到了实现这一目标的状态.

我在不同单元之间转换的核心在于以下通用模板函数:

template <class SrcUnit, class TgtUnit> extern
double convert(double val);
Run Code Online (Sandbox Code Playgroud)

该函数的目标是将以类型SrcUnit为单位表示的物理量值转换为以类型为单位表示的另一物理量值TgtUnit.

我有一个叫做Quantity<Unit>管理值及其统一的类,这个类试图给出类型安全和自动转换.例如,我导出以下构造函数:

  template <class SrcUnit>
  Quantity(const Quantity<SrcUnit> & q)
    : unit(UnitName::get_instance())
  {
    check_physical_units(q); // verify that the physical magnitudes are the same
    value = convert<SrcUnit, UnitName>(q.value); // <<- here the conversion is done
    check_value(); // check if the value is between the allowed interval
  }
Run Code Online (Sandbox Code Playgroud)

我导出转换完成的其他东西.

因此,当有人希望管理新单元时,她会指定一个新的Unit派生类.我通过在宏中放入新类的所有必需规范来实现这一点.现在,该用户有责任编写转换函数.那就是编写convert()模板的两个特化.例如,假设您有一个名为'Kilometer and you wish to specify a new unit calledMile` 的单位.在这种情况下,您执行此操作:

Declare_Unit(Mile, "mi", "English unit of length", Distance,
         0, numeric_limits<double>::max()); // macro instantiating a new Unit class
template <> double convert<Kilometer, Mile>(double val) { return val/1609.344; }
template <> double convert<Mile, Kilometer>(double val) { return 1609.344*val; }
Run Code Online (Sandbox Code Playgroud)

现在,如果用户忘记编写转换函数会发生什么?那么,在这种情况下,链接器将失败,因为它无法找到特化convert().

现在我的问题.

虽然我认为链接器错误是可接受的,因为向用户报告缺失的行为convert(),我想测试我编译convert()专业化存在的时间.所以我的问题是如何实现这一目标?我想static_assert在每次调用之前通过一个put来convert()判断专业化是否已经知道.但是怎么做呢?

PS:另外,如果有人能推荐我关于C++元编程的好文本,对我来说非常有用.

101*_*010 4

您可以通过static_assert在主函数模板中放置一个小技巧来做到这一点,这将确保您的程序不会格式错误,不会从这里无耻地窃取:

template <typename...> struct always_false : std::false_type {};

template<typename T, typename U> double convert(double) {
  static_assert(always_false<T, U>::value, "No specialization exists!");
}

template <> double convert<Kilometer, Mile>(double val) { return val/1609.344; }
template <> double convert<Mile, Kilometer>(double val) { return 1609.344*val; }
Run Code Online (Sandbox Code Playgroud)

现场演示