OK, I\'ll just post the complete program even though it has extraneous stuff and the code in question is the dead code…
#include
#include
The difference is that ifstream isn't visible as an injected class name because it is the name of a typedef, not the name of the class. It isn't therefore visible unqualified as an injected class name from the base class.
ios_base is a genuine class name which is a base class (of a base class) of the class where it is used and so is visible unqualified as an inject class name.
E.g.
namespace X
{
class A {};
template class Z {};
typedef Z B;
}
class C : public X::A
{
C() : A() {} // OK, A is visible from the base class
};
class D : public X::B
{
D() : B() {} // Error, B is a typedef,
// : X::B(), : Z() or even : Z() can be used.
};
In your example, instead of std::ifstream, you can use unqualified basic_ifstream instead. (Or basic_ifstream or basic_ifstream but these don't really save any typing or help clarity at all.)