Reputation: 56
I've got a class called number and I'm needing help with operator overloading.
template<class T>
class Number{
public:
Number(T _numerator,T _denominator){
numerator = _numerator;
denominator = _denominator;
}
~Number(){
;
}
T GetData(){
return numerator/denominator;
}
friend std::ostream &operator<<(std::ostream &out, Number c) //output
{
out << c.numerator/c.denominator;
return out;
}
void SetData(T _numerator,T _denominator){
numerator = _numerator;
denominator = _denominator;
}
private:
T numerator;
T denominator;
};
that's what I have that works but I would like another operator overloaded like:
template<class X>
friend std::ostream &operator<<(std::ostream &out, Number c) //output
{
out << (X)c.numerator/(X)c.denominator;
return out;
}
that way I can call cout like this(I know I could just change Number's template to a double but that's not what I want):
Number<int> t(10,23);
std::cout << t<double> << "\n";
however that doesn't compile. so is there anyway to use templates like that? or an alternate solution other than just creating a normal function?
Upvotes: 2
Views: 144
Reputation: 66194
You can get close to what you're looking for any number of ways. The exact syntax you want is impossible unfortunately , as the type you desire must be pinned through something (be it a function, a constructed object, whatever).
Vinzenz has shown you how to you can pin it through a member function. This is how you can pin it through an alternate constructor.
#include <iostream>
template<class T>
class Number
{
// allow friending alternate types
template<typename> friend class Number;
friend std::ostream &operator<<(std::ostream &out, Number c) //output
{
out << c.GetData();
return out;
}
public:
Number(T _numerator = 0, T _denominator = 1)
: numerator(_numerator)
, denominator(_denominator)
{
}
// constructor for alt-type conversion
template<typename X>
Number(const Number<X>& obj)
: numerator(static_cast<T>(obj.numerator))
, denominator(static_cast<T>(obj.denominator))
{
}
// getter should be const
T GetData() const
{
return numerator/denominator;
}
void SetData(T _numerator,T _denominator)
{
numerator = _numerator;
denominator = _denominator;
}
private:
T numerator;
T denominator;
};
int main()
{
Number<int> num(10,5); // regular construction
Number<float> flt = num; // alternate type construction
// operator tests
std::cout << num << '\n';
std::cout << flt << '\n';
std::cout << Number<double>(num) << std::endl; // temp construction
return EXIT_SUCCESS;
}
Output
2
2
2
Best of luck.
Upvotes: 1
Reputation: 2819
I think you're thinking too complicated about it and the way you want to use it, won't work.
When you need it to be Double, make it double, so therefore I added here the new member as()
template<class T>
class Number{
public:
Number(T _numerator,T _denominator){
numerator = _numerator;
denominator = _denominator;
}
~Number(){
;
}
T GetData(){
return numerator/denominator;
}
friend std::ostream &operator<<(std::ostream &out, Number c) //output
{
out << c.numerator/c.denominator;
return out;
}
void SetData(T _numerator,T _denominator){
numerator = _numerator;
denominator = _denominator;
}
template<typename U>
Number<U> as(){
return Number<U>(U(numerator), U(denominator));
}
private:
T numerator;
T denominator;
};
Number<int> t(10,23);
std::cout << t.as<double>() << "\n";
Upvotes: 1