class A
{
...
A operator =(A &rhs);
A template<typename T> operator =(const T &rhs);
A operator -(A &rhs);
}
int main(void)
{
A number;
A otherNumber;
A result;
number="123"; //calls templated operator = as expected
otherNumber="321"; //calls templated operator = as expected
result=number - otherNumber; //calls templated operator = in error
}
I
don't not understand why the templated version of the assignment
operator is being called when minus operator returns an object of type
A. The last line should resolve to:
A = A
After the call to the
minus operator which should have the compiler call the non-templated
version of the assignment operator yet the compiler selects the
templated version and causes my program to error out.
Can someone explain to me why this is happening
Also
I've tried to resolve the issue by creating an explicit template
specialization for the assignment operator but VS2005 gives me errors.
I tried:
template <> operator =<>(A &rhs);
and
template <> operator =<A>(A &rhs);
I
got errors for unexpected tokens etc. despite not being able to see
syntax errors in the declarations. Is the syntax wrong Does VS not
support specialization of operators Does C++ allow explicit template
specializations of operators
Thankyou to anyone who gives up their time to help me.

Compiler selecting template function in error?
Marcos B
SteveTaylorMST
#define _MYINTEGER_H_
#include "smartpointer.h"
#include <iostream>
#include <sstream>
using std::ostream;
using std::istream;
using std::stringstream;
using std::cerr;
using std::endl;
class MyInteger
{
public:
MyInteger();
MyInteger(const char *integer);
MyInteger(unsigned int &sz);
MyInteger(MyInteger &myInt);
~MyInteger();
...
...
MyInteger operator =(MyInteger &rhs);
template<typename T>
MyInteger operator =(const T &rhs);
MyInteger operator -(MyInteger &rhs);
template<typename T>
MyInteger operator -(const T &rhs);
...
...
friend ostream& operator <<(ostream &output,const MyInteger &rhs);
friend istream& operator >>(istream &input,MyInteger &rhs);
private:
template<typename T>
unsigned int calcSize(const T &str);
template<>
unsigned int calcSize<smartpointer<char>>(const smartpointer<char> &str);
template<typename T>
void convertToMyInter(const T &unvalidated,MyInteger *validated);
void addSign(MyInteger &results);
void clearZeros(MyInteger &results);
void subtract(MyInteger &results,MyInteger lhs,const MyInteger &rhs);
...
...
void reset();
unsigned int size;
smartpointer<char> digits;
};
#include "MyInteger.inl"
#endif
------------------------------------------
//////////////////////from MyInteger.inl
template<typename T> void MyInteger::convertToMyInter(const T &unvalidated,MyInteger *validated)
{
//local variables
char someChar;
unsigned int sentry;
bool signedFlag=false;
stringstream sStream;
int numDecimalPoints=i_zero;
validated->size=calcSize(unvalidated)+i_one;
validated->digits=new char[validated->size];
sStream<<unvalidated;
for(unsigned int i=i_zero;i<validated->size-i_one;++i)
{
someChar=sStream.get();
if(i==0)
{
if(someChar=='-')
{
validated->digits
signedFlag=true;
}
else if(someChar>'9' && someChar<'0')
{
cerr<<"Fatal Error! "<<unvalidated<<" is not a valid integer. Program terminated."<<endl;
exit(-1);
}
else
{
validated->digits
}
}
else if(someChar=='.')
{
(signedFlag) sentry=i_one : sentry=i_zero;
if(!numDecimalPoints && i>sentry)
{
validated->digits
++numDecimalPoints;
}
else
{
cerr<<"Fatal Error! "<<unvalidated<<" is not a valid integer. Program terminated."<<endl;
exit(-1);
}
}
else if(!numDecimalPoints)
{
if(someChar>'9' || someChar<'0')
{
cerr<<"Fatal Error! "<<unvalidated<<" is not a valid integer. Program terminated."<<endl;
exit(-1);
}
else
{
validated->digits
}
}
else
{
if(someChar != '0')
{
cerr<<"Fatal Error! "<<unvalidated<<" is not a valid integer. Program terminated."<<endl;
exit(-1);
}
else
{
validated->digits
}
}
}
validated->digits[validated->size-i_one]='\0';
}
template<typename T> MyInteger MyInteger::operator =(const T &rhs)
{
convertToMyInter(rhs,this);
return *this;
}
//////////////////////////from MyInteger.cpp
MyInteger MyInteger::operator =(MyInteger &rhs)
{
if(*this!=rhs)
{
this->size=rhs.size;
this->digits=rhs.digits;
}
return *this;
}
MyInteger MyInteger::operator -(MyInteger &rhs)
{
//local variables
bool negLhs;
bool negRhs;
MyInteger temp;
(this->digits[i_zero]=='-') negLhs=true : negLhs=false;
(rhs.digits[i_zero]=='-') negRhs=true : negRhs=false;
if(this->size > rhs.size)
{
temp.digits=new char[this->size];
temp.size=this->size;
subtract(temp,*this,rhs);
if(negLhs)
{
addSign(temp);
clearZeros(temp);
return temp;
}
else
{
clearZeros(temp);
return temp;
}
}
else if(rhs.size > this->size)
{
temp.digits=new char[rhs.size];
temp.size=this->size;
subtract(temp,rhs,*this);
if(negLhs)
{
addSign(temp);
clearZeros(temp);
return temp;
}
else
{
clearZeros(temp);
return temp;
}
}
else
{
//get significant digit info
//the one with the significant sign wins
for(unsigned int i=i_zero;i<this->size;++i)
{
if(this->digits
{
temp.digits=new char[this->size];
temp.size=this->size;
subtract(temp,*this,rhs);
if(negLhs)
{
addSign(temp);
clearZeros(temp);
return temp;
}
else
{
clearZeros(temp);
return temp;
}
break;
}
else if(rhs.digits
{
temp.digits=new char[rhs.size];
temp.size=this->size;
subtract(temp,rhs,*this);
if(negLhs)
{
addSign(temp);
clearZeros(temp);
return temp;
}
else
{
clearZeros(temp);
return temp;
}
break;
}
}
temp.digits=new char[2];
temp.digits[i_zero]='0';
temp.digits[i_one]='1';
return temp;
}
}
-------------------------------------------
#include "smartpointer.h"
#include "digits.h"
#include "MyInteger.h"
#include <vector>
using namespace std;
int main(void)
{
MyInteger someInt();
MyInteger dummy;
someInt="321";
dummy="123";
someInt=(dummy-someInt); //errors out here
cout<<someInt<<endl;
cout<<someInt[someInt.getSize()]<<endl;
return i_zero;
}
----------------------------------------------------
I need to handle MyInteger's differently when assigning values from one to another.
I use a template to assign values stored in integral types to MyInteger.
The member convertToMyInteger checks that values passed into the template function are valid integers.
If one where to pass in -1 to convertToMyInteger it would accept the value as the assignment would complete.
If one where to pass in a MyInteger storing -1 to convertToMyInteger the function will error out due to how values are internally validated. However, that is the reason there is overload of the assignment operator that handles objects of type MyInteger. It would make much sense for an MyInteger instance to not be an integer.
My problem lies with the template function being selected by the compiler in preferrence to the non-template assignment operator overload.
I don't understand why this is happening or how to prevent it from happening. I will appreciate any help anyone can give me.
Tiarnan
I didn't want to use a deep copy because I was using a reference counted smart pointer. However, when I think about it I don't want operations with one instance to affect another so I would seem a deep copy is the only thing that makes sense after all.
Thanks. I'll change that.
I'll add the const keyword too :)
glenna
PiGuy
I am curious to know whether explicit specializations are not allowed only in this case or in general when it comes to operators.
Anyhow writing a non-template copy assignment operator rectified the issue.
Thanks to all for helping me. And to anyone who would bother to answer my implied question :)
MarcNelson
I'm not exactly certain what you're trying to achieve, but obviously operator- will return a rvalue and a non-const reference can't bind to a temporary. I don't think there's anything special in this case that would require selection of the copy-assignment operator. Either way, it would be ill-formed at best.
So you might want to define a copy-assignment operator with a const argument.
The second specialization looks good, but you're missing the const. You could also let the compiler deduce arguments which requires you to omit the angle brackets.
-hg
Joe_Cool