c++ - 仅在未被 std::enable_if 禁用时才调用成员函数

标签 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
          }
      }
};

一切都很好,除了我重载的时候<<为类(class)。

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 禁用了所以我得到了同样的编译器错误。有没有办法修改该答案以捕获该功能存在但被禁用的事实?

最佳答案

您可以创建一个专门的 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);
}

关于c++ - 仅在未被 std::enable_if 禁用时才调用成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33057058/

相关文章:

c++ - 在 C++ 中检测运算符是否存在和可调用(考虑 static_asserts)

c++ - "lazy man' s enable_if"是合法的 C++ 吗?

c++ - 使用 C++17 检测仿函数的类型特征?

c++ - 从 double 到无符号 64 位整数的安全转换

c++ - "error: subscripted value is not an array, pointer, or vector"我正在使用一个字符串

c++ - 没有规则使目标 '/usr/lib/x86_64-linux-gnu/libboost_filesystem.so`

c++ - 如何使用 SFINAE 从 end() 方法返回 (const_)iterator

c++ - 如何在浏览器进程中调用CefV8Context::Eval()方法?

c++ - 使用 biicode cmake 在 Debug模式下构建 C++

c++ - 避免重复 SFINAE 区分无效和非无效返回类型