Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is no qualification necessary?

Tags:

c++

OK, I'll just post the complete program even though it has extraneous stuff and the code in question is the dead code…

#include <iostream>
#include <fstream>

namespace detail {
    // Solution by Johannes Schaub alias litb
    // http://groups.google.com/group/comp.std.c++/browse_thread/thread/b567617bfccabcad
    template<int> struct D {};
    typedef char yes[1];
    typedef char no[2];

    template< class T, class U >
    yes& f( int, D< sizeof T(*(U*)0) >* = 0 );

    template< class T, class U >
    no& f( ... );

    template< class To, class From >
    struct IsExplicitlyConvertible
    {
        enum{ yes = (sizeof detail::f< To, From >(0) == sizeof( detail::yes ) ) };
    };

    bool const streamsSupportWindows =
        IsExplicitlyConvertible< std::ofstream, wchar_t const* >::yes;
}

class InFStream
    : public std::ifstream
{
    public:
        InFStream() {}
        explicit InFStream(
            char const* filename,
            ios_base::openmode mode = ios_base::in | ios_base::out
            )
            : std::ifstream( filename, mode )
        {}
};

int main()
{
    using namespace std;
    cout << (detail::streamsSupportWindows
        ? "Windows-enabled"
        : "Ach, no Windows support"
        ) << endl;
}

This compiles fine with MSVC and g++. But in the InFStream class, why do I not need to qualify ios_base? Or, same question really, why do I need to use std:: qualification of ifstream in the constructor initializer list?

like image 331
Cheers and hth. - Alf Avatar asked Oct 23 '11 17:10

Cheers and hth. - Alf


People also ask

Are qualifications necessary?

Qualifications show your knowledge and skills building in a specialist subject. If you achieve a qualification in a specialist subject like engineering, employers know you have developed not just the life skills but also the concrete knowledge they need to offer you the job.

Do qualifications matter?

Qualifications are more important The benefits affect all parts of life; intellectual, social, sporting, personal, artistic, ethical, and so much more. Recruiters often write job advertisements that specify that a degree is needed for the job, thus the market decides on this point, and it values degrees.

Why it is important for the job holder to have the qualifications?

Employers prefer diploma-holders This is because your qualifications give employers an idea of what you know and are capable of accomplishing. The better credentials you have, the greater the likelihood that you can deliver the output they will require of you.


2 Answers

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> class Z {};
    typedef Z<char> 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<char>() or even : Z() can be used.
};

In your example, instead of std::ifstream, you can use unqualified basic_ifstream instead. (Or basic_ifstream<char> or basic_ifstream<char, std::char_traits<char> > but these don't really save any typing or help clarity at all.)

like image 200
CB Bailey Avatar answered Sep 28 '22 03:09

CB Bailey


Some thoughts about why you have to specify std::ifstream in constructor's initializer . I think typedef is the culprit - ifstream is defined as typedef basic_ifstream<char, char_traits<char> > ifstream;). If you change your constructor to

 explicit InFStream(
    char const*         filename,
    ios_base::openmode  mode =  ios_base::in | ios_base::out

    ):
    basic_ifstream<char,std::char_traits<char>>( filename, mode ){}

you also don't have to specify std::basic_ifstream. I cannot find details about why typedef works this way, but the problem is reproducible. For instance,

namespace test1
{
class A {

public :
    static const int cn = 1;

    virtual ~A();
    A(int t): x(t){};
    int x;
};

class B:public A
{
public:
    B(int t) : A(t){};
};
typedef B XX;  
};  
class C:public test1::XX
{
  int aaa;
    public:
explicit  C(int x) :XX(x) // error  
explicit  C(int x) :test1::XX(x) // ok
explicit  C(int x) :B(x) // also ok
{       
    aaa = A::cn;
};
};
like image 41
a1ex07 Avatar answered Sep 28 '22 03:09

a1ex07