Reputation: 23
I'm setting up an Average class and fell over following problem:
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_);
}
}
...
};
When I create the instance of Average like this:
Average<double, double> m_avg;
I get the error, that the operator double is already defined.
I understand that the operator is defined 2 times now. But how do I solve the problem? I want that the operator double() is called when double is casted and all other types call T()
Upvotes: 0
Views: 135
Reputation: 217135
In C++2a, you may discard method thanks to requires
:
operator T() const requires (!std::is_same<double, T>::value) {/*code*/}
Before that SFINAE on method (making it template) or (partial) specialization of the class might solve the issue.
Upvotes: 2
Reputation: 13988
To answer your explicit question - you could make your first overload template and disable it for all other types than double by using of SFINAE mechanism. The template function has a lower priority than non-template overloads so it wouldn't match in case when T==double.
Exemplary code:
#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;
}
Output:
general version double version
Note that if it need to be pre-c++17 use typename std::enable_if<std::is_same<D, double>::value>::type
instead of std::enable_if_t<std::is_same_v<D, double>, int>
.
Upvotes: 2
Reputation: 23497
Another solution not based on 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;
}
Live demo: https://wandbox.org/permlink/vT4DTCWiEOkPWlhu
Upvotes: 0