I seem to be having an issue with a simple program. The error messages I am getting is this:
1 2 3 4 5 6 7 8
main.cpp: In member function ‘Token& Token::operator=(int)’:
main.cpp:36:15: error: expected class-name before ‘(’ token
sval.~string(); // if we have a string, free it
^
main.cpp: In member function ‘Token& Token::operator=(const Token&)’:
main.cpp:76:15: error: expected class-name before ‘(’ token
sval.~string();
#include <string>
class Token
{
public:
// copy control needed because our class has a unioin with a string
Token() : tok(INT), ival{0} { }
Token(const Token &t) : tok(t.tok) { copyUnion(t); }
Token &operator=(const Token&);
// if the union holds a string, we have to destroy it
~Token() { using std::string; if (tok == STR) sval.~string(); }
Token &operator=(const std::string&);
Token &operator=(char);
Token &operator=(int);
Token &operator=(double);
private:
enum {INT, CHAR, DBL, STR} tok;
union
{
char cval;
int ival;
double dval;
std::string sval;
}; // each Token object has an unnamed member of this unnamed union type
// check the discriminant and copy the union member as appropriate
void copyUnion(const Token&);
};
Token &Token::operator=(int i)
{
if (tok == STR)
sval.~string(); // if we have a string, free it
ival = i; // assign to the appropriate member
tok = INT; // update the discriminant
return *this;
}
Token &Token::operator=(const std::string &s)
{
if (tok == STR)
sval = s;
elsenew(&sval) std::string(s);
tok = STR;
return *this;
}
void Token::copyUnion(const Token &t)
{
switch (t.tok)
{
case Token::INT:
ival = t.ival;
break;
case Token::CHAR:
cval = t.cval;
break;
case Token::DBL:
dval = t.dval;
break;
case Token::STR:
new(&sval) std::string(t.sval);
break;
}
}
Token &Token::operator=(const Token &t)
{
// if this object holds a string and t doesn't, we have to free the old string
if (tok == STR && t.tok != STR)
sval.~string();
if (tok == STR && t.tok == STR)
sval = t.sval;
else
copyUnion(t);
tok = t.tok;
return *this;
}
int main()
{
Token t;
return 0;
}
Error is on line 34 and 74, it is fixed when and add using namespace std;
Can you also explain why this error does not appear on line 14.
Thank you, cheers!
Edit: I should have also added that adding std:: before string does not fix the issue.
You should not be calling the destructor, ever. The only time it is valid to manually call the destructor is if you used placement new (which has very rare use cases). The compiler adds code to your class destructor for you that destructs your class members.
I don't even know why the compiler allows you to have a std::string in a union, that is not valid C++. You should not be doing that at all - don't put non-POD types in unions and don't use placement new for this.
// ...
Token &Token::operator=(int i)
{
using std::string ; // **** added
if (tok == STR)
sval.~string(); // if we have a string, free it
ival = i; // assign to the appropriate member
tok = INT; // update the discriminant
return *this;
}
// ...
Token &Token::operator=(const Token &t)
{
// if this object holds a string and t doesn't, we have to free the old string
using std::string ; // **** added
if (tok == STR && t.tok != STR)
sval.~string();
if (tok == STR && t.tok == STR)
sval = t.sval;
else
copyUnion(t);
tok = t.tok;
return *this;
}
// ...
Thank you and yes that solves my problem but I still don't know why. Why can't I specify std::? And how come Token's destructor on line 12 works? Thank you again!