范本Cast-Operator规格

时间:2019-01-24 07:41:56

标签: c++

我正在设置一个普通班,却遇到了以下问题:

template <typename T, typename Total>
class Average
{
public:
  Average(...){ ... }

...

operator double() const
{
  if (num_samples_ == 0)
  {
    return 0;
  }
  else
  {
    return static_cast<double>(total_) / num_samples_;
  }
}

operator T() const
{
  if (num_samples_ == 0)
  {
    return 0;
  }
  else
  {
    return round<T>(total_ / num_samples_);
  }
}
...
};

当我这样创建Average实例时:

Average<double, double> m_avg;

我得到一个错误,已经定义了运算符double。

我了解到该运算符已被定义2次。但是我该如何解决这个问题呢?我希望在转换double时调用运算符double(),而所有其他类型都调用T()

3 个答案:

答案 0 :(得分:2)

要回答您的明确问题-您可以使用SFINAE机制制作第一个重载模板,并对除double以外的所有其他类型禁用它。模板函数的优先级比非模板重载的优先级低,因此,当T == double时,它将不匹配。

示例代码:

#include <iostream>
#include <type_traits>

template <class T>
struct Foo {
    template <class D, std::enable_if_t<std::is_same_v<D, double>, int> = 0>
    operator D() {
        std::cout << "double version" << std::endl;
        return 0.0;
    }

    operator T() {
        std::cout << "general version" << std::endl;
        return T{};
    }
};

int main() {
    Foo<double> fd;
    (double)fd;
    Foo<int> fi;
    (double)fi;
}

输出:

general version 
double version

(Live demo)

请注意,如果需要在c ++ 17之前使用,请使用typename std::enable_if<std::is_same<D, double>::value>::type而不是std::enable_if_t<std::is_same_v<D, double>, int>

答案 1 :(得分:2)

在C ++ 2a中,由于requires,您可以放弃方法:

operator T() const requires (!std::is_same<double, T>::value) {/*code*/}

在SFINAE的方法(使其成为模板)或类的(部分)专业化之前,可以解决该问题。

答案 2 :(得分:0)

另一种不基于SFINAE的解决方案:

#include <type_traits>

template <typename T>
struct X {
  using T_ = typename std::conditional<std::is_same<T, double>::value, void, T>::type;
  operator double() { return double{}; }
  operator T_() { return T_{}; }
};

int main() {
  X<int> xi;
  X<double> xd;
}

实时演示:https://wandbox.org/permlink/vT4DTCWiEOkPWlhu