Is this a bug with GCC?

How can the presence of an ofstream data member of a base class prevent the casting to a subclass? If I leave the ofstream data member in Person, GCC 4.8.1 complains that the static_cast is ambiguous. With Microsoft Visual C++ 2012, it compiles fine if the ofstream data member remains in Person.
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
class Person { 
	private:
		std::string name;
		//std::ofstream personFile;   // With this in, the program won't compile because it considers the static_cast ambiguous
};

class Girl: public Person {};

class Cheerleader: public Girl {
	private:
		int cheeringSkill;
	public:
		Cheerleader () {}
		Cheerleader (const Girl&);  // constructor to allow conversion of Girl to type Cheerleader
};

Cheerleader::Cheerleader (const Girl& girl) {}

int main () {
	Girl Mary;
	std::cout << typeid (Mary).name() << std::endl; 
	Cheerleader _Mary = static_cast<Cheerleader> (Mary);
	std::cout << typeid (_Mary).name() << std::endl;  // type cast successful
  	return 0;
}
Last edited on
Running your code in school's linux server gave this error.

code.cpp: In function ‘int main()’:
code.cpp:24:12: error: expected ‘;’ before ‘typeid’
code.cpp:26:12: error: expected ‘;’ before ‘typeid’


Which was fixed with the following.
1
2
3
4
5
#include <typeinfo>
...
std::cout << typeid (Mary).name() << std::endl;
Cheerleader _Mary = static_cast<Cheerleader> (Mary);
std::cout << typeid (_Mary).name() << std::endl;  // type cast successful 
Last edited on
std::ios_base isn't copyable.
See: http://en.cppreference.com/w/cpp/io/ios_base/ios_base

Clang doesn't compile this either, saying "base class 'std::ios_base' has private copy constructor".
vasilenko93 (45)
Running your code in school's linux server gave this error.


code.cpp: In function ‘int main()’:
code.cpp:24:12: error: expected ‘;’ before ‘typeid’
code.cpp:26:12: error: expected ‘;’ before ‘typeid’




Which was fixed with the following.

#include <typeinfo>
...
std::cout << typeid (Mary).name() << std::endl;
Cheerleader _Mary = static_cast<Cheerleader> (Mary);
std::cout << typeid (_Mary).name() << std::endl; // type cast successful


#include <typeinfo> was in my code, I just didn't paste any of the #includes here. But did this compile when you allowed the ofstream data member to be in Person, i.e. uncommented 'std::ofstream personFile;'?

According to SneakySnake (5), it actually is not supposed to compile in that case. In that case, the bug is not in GCC but in Microsoft Visual C++ for allowing it to be compiled when it shouldn't.
Last edited on
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
#include <iostream>
#include <fstream>
#include <typeinfo>

struct Person{

    Person() = default ;
    Person( const Person& that ) : name(that.name) { /* can't copy std::ofstream */ }
    Person( Person&& that ) noexcept = default ;

	private:
	    std::string name;
		std::ofstream PersonFile;
};

class Girl: public Person {};

class Cheerleader: public Girl {
	private:
		int cheeringSkill;
	public:
		Cheerleader () {}
		Cheerleader (const Girl&);  // constructor to allow conversion of Girl to type Cheerleader
};

Cheerleader::Cheerleader (const Girl& girl) {}

int main () {
	Girl Mary;
	std::cout << typeid (Mary).name() << std::endl;
	Cheerleader _Mary = static_cast<Cheerleader> (Mary);
	std::cout << typeid (_Mary).name() << std::endl;  // type cast successful
  	return 0;
}

http://coliru.stacked-crooked.com/a/6a258333bbddd698
Thanks JLBorges for finding the solution to the problem. Your solution works, but I had to remove the line
Person( Person&& that ) noexcept = default ;
(my Person class is actually an abstract class due to its many pure virtual functions, and I think that might be the reason why this line won't compile. Update: I ran a test, and Person being abstract is not the reason why the above line won't compile, but some other reason I have yet to find). error: function 'Person::Person(Person&&)' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'Person::Person(Person&&)'

Is that line really necessary? I haven't studied references to rvalue expressions yet, but will today. I ran my program and it so far has no problems without that line. Incidentally, the Person copy constructor is never being called, even though that was needed to solve the problem.
Last edited on
> Is that line really necessary?

No. Not unless we want to make person moveable.


> Funnily, the Person copy constructor is not ever being called either, even though that was needed to solve the problem.

Copy initialization is less permissive than direct initialization.
http://en.cppreference.com/w/cpp/language/copy_initialization

EDIT:

> error: function 'Person::Person(Person&&)' defaulted on its first declaration
> with an exception-specification that differs from the implicit declaration
'Person::Person(Person&&)'

Yes, mea culpa. std::ifstream is not no-throw-move-constructible.
http://en.cppreference.com/w/cpp/io/basic_ifstream/basic_ifstream

Person( Person&& that ) /*noexcept*/ = default ;
Last edited on
> Yes, mea culpa. std::ifstream is not no-throw-move-constructible.
Ah. Now the line compiles, so now Person is moveable as a bonus. You guessed correctly that Person has ifstream data members too. Thank you so much. You are also the first person to answer my first post in this forum when I was a total beginner a few months ago.
Topic archived. No new replies allowed.