expected class name error

Hello lads,

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();


Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

#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;
	else
		new(&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.
Last edited on
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.
Last edited on
@LB I am using placement new on lines 45 and 65, I will also be using it in a few other assignment operators which I have not defined yet.
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ...

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;
}

// ... 

http://coliru.stacked-crooked.com/a/4c50762a16fe3c05


> You should not be calling the destructor, ever.
>> don't put non-POD types in unions and don't use placement new for this.

See: http://www.stroustrup.com/C++11FAQ.html#unions
@JLBorges

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!
@JLBorges: I didn't realize the relaxed restrictions allowed a std::string in unions. That still just doesn't feel right to me.
> Why can't I specify std::?

The name of the destructor of std::string is just ~string.


> And how come Token's destructor on line 12 works?

~Token() { using std::string; if (tok == STR) sval.~string(); }
@JLBorges Thanks again mate, totally flew over my head.
Topic archived. No new replies allowed.