【问题标题】:call member function only if not disabled by std::enable_if仅当未被 std::enable_if 禁用时才调用成员函数
【发布时间】:2015-10-10 17:43:48
【问题描述】:

我正在编写一个函数来计算数值流的各种统计信息。它有各种模板参数来有条件地计算其他更昂贵的东西,比如中位数和众数。它们是模板,因此编译器将优化所有 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
          }
      }
};

一切都很好,花花公子,除了我去超载&lt;&lt;上课。

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&lt;&lt;,因此它不使用 if 语句,但我计划包含至少 3 个参数,这已经是函数的 8 个变体我得写。添加更多模板参数将是一个巨大的痛苦。

我已经尝试过this answer中的方法,但是还是不行。测试方法给出了true_type,因为该方法确实存在,它只是被enable_if 禁用,所以我得到相同的编译器错误。有没有办法修改该答案以捕捉该功能存在但被禁用的事实?

【问题讨论】:

    标签: c++ sfinae


    【解决方案1】:

    你可以创建一个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);
    }
    

    【讨论】:

    • 这肯定行得通,而且很容易添加更多标志。我猜我想多了——谢谢!
    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多