我正在设置一个普通班,却遇到了以下问题:
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()
答案 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
请注意,如果需要在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;
}