仅当std :: enable_if未禁用时才调用成员函数

时间:2015-10-10 17:43:49

标签: c++ sfinae

我正在编写一个计算数值数值流的各种统计数据的函数。它有各种模板参数来有条件地计算其他更昂贵的东西,如中位数和模式。它们是模板,因此编译器将优化所有if语句。根据模板值,如果不计算更昂贵值的getter,则会禁用它们。

template <bool CalcMedian>
class Stats
{
public:
      // median getter, disabled if it wasn't calculated
      template <bool B = CalcMedian, typename = std::enable_if_t<B>>
      double median() const { return _median; }

      void add_element(double value) {
          // update easy values
          if (CalcMedian) {
              // update the median
          }
      }
};

除非我为班级重载<<,否则一切都很好。

template <bool CalcMedian>
std::ostream& operator<<(std::ostream& o, const Stats<CalcMedian>& stats) {
    // display the easy stats
    if (CalcMedian) {
        o << "median = " << stats.median();
        // g++: no matching function call for Stats<false>::median()
    }
}

一种解决方案是专门用于删除getter,或operator<<,因此它不会使用if语句,但我计划至少包含3个参数,这是已经有8种函数我不得不写。添加更多模板参数将是一个巨大的痛苦。

我已经尝试了this answer中说明的方法,但它不起作用。测试方法提供true_type,因为该方法确实存在,它只是被enable_if禁用,因此我得到相同的编译器错误。有没有办法修改该答案以捕获函数存在但被禁用的事实?

1 个答案:

答案 0 :(得分:2)

您可以创建display_median专门的:

template <bool B = CalcMedian>
std::ostream&o display_median(std::ostream&o) const;

template <>
std::ostream&o display_median<true>(std::ostream&o) const;
{
    return o << "median = " << median() << std::endl;
}

template <>
std::ostream&o display_median<false>(std::ostream&o) const;
{
    return o;
}

然后

template <bool CalcMedian>
std::ostream& operator<<(std::ostream& o, const Stats<CalcMedian>& stats) {
    // display the easy stats
    stats.display_median<CalcMedian>(o);
}