好吧,我会发布完整的程序,即使它有无关的东西,而且有问题的代码是死代码......
#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;
}
Run Code Online (Sandbox Code Playgroud)
这与MSVC和g ++编译良好.但在InFStream课堂上,为什么我不需要资格ios_base?或者,同样的问题,为什么我需要在构造函数初始化列表中使用std::限定条件ifstream?
不同之处在于,ifstream作为注入的类名称不可见,因为它是a的名称typedef,而不是名称class.因此,作为基类中的注入类名,它不可视为不合格.
ios_base 是一个真正的类名,它是使用它的类的基类(基类),因此作为注入类名可见不合格.
例如
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.
};
Run Code Online (Sandbox Code Playgroud)
在您的示例中std::ifstream,您可以使用不合格,basic_ifstream而不是.(或者,basic_ifstream<char>或basic_ifstream<char, std::char_traits<char> >但这些真的不保存任何打字或帮助的清晰度都没有.)
关于为什么必须std::ifstream在构造函数的初始化程序中指定的一些想法.我认为typedef是罪魁祸首 - ifstream被定义为typedef basic_ifstream<char, char_traits<char> > ifstream;).如果您将构造函数更改为
explicit InFStream(
char const* filename,
ios_base::openmode mode = ios_base::in | ios_base::out
):
basic_ifstream<char,std::char_traits<char>>( filename, mode ){}
Run Code Online (Sandbox Code Playgroud)
你也没必要指定std::basic_ifstream.我找不到有关为什么这样typedef工作的细节,但问题是可重现的.例如,
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;
};
};
Run Code Online (Sandbox Code Playgroud)