VC6のダメなとこをまとめておく【随時更新(予定)】

いったいぜんたいどこがダメなのよって話をあまり聞かない
forがダメだとかテンプレートがダメとか
じゃあどういう風にダメなのよって調べてまとめてみた

  • エラーコードが書いてあるのは対象の下の行でエラーがでるってこと
  • 解決策がないのは解決法を募集あるいは無理

同じテンプレートで明示を変更するのがダメ

template <int N>
void foo1(int a)
{
	std::cout << N << ":" << a << std::endl;
};
int main(int argc, char *argv[]){
 foo1<1>(2);	//2:2って表示されるよ!なんで?
 foo1<2>(2);
}

これはintだけどもちろん型名でも同様

解決法
template <int N>
class foo1_a
{
public:
	void operator()(int a)
	{
		std::cout << N << ":" << a << std::endl;
	};
};
int main(int argc, char *argv[]){
 foo1_a<1>()(2);
 foo1_a<2>()(2);
}

for

void foo2()
{
	for(int i=0;i<5;i++) std::cout << i << std::endl;
	//↓C2374
	for(int i=5;i<10;i++) std::cout << i << std::endl;
}
解決策

どこかのヘッダに書きましょう

#define for if(0); else for

同名メンバのテンプレート

template <class T>
class foo3
{
public:
	foo3(){}
	//↓C2535
	template <class U>
	foo3(){}
};

クラス内static const

class foo4
{
public:
	foo4():i(20){} //これは通る!ふしぎ!
	//C2258
	const static int i = 20;
};
解決策

クラス外で

const static int foo4::i = 20;

それか、enum化しちゃう
boost/config/suffix.hppはこれをやってる

class foo4
{
public:
 enum { i = 20 };
};

ただこれだと、定数じゃなくて式だった場合にコンパイルできない
こんなのね

//そもそもstd::size_tがなくてsize_tって書かないといかんのだけどそれは別として
template <std::size_t N>
struct pow2{
 static const std::size_t value = N * N;
};

テンフレート関数のPartial Ordering

template<class T> void foo5( T ) {	std::cout << "foo5( T ) called." << std::endl;};
template<class T> void foo5( T* ){	std::cout << "foo5( T* ) called." << std::endl;};
template<class T> void foo5( const T* ) {	std::cout << "foo5( const T* ) called." << std::endl;};
int main(int argc, char *argv[]){
 foo5( a );
 int	*p;
 const int *cp;
 foo5( p );		//C2667,C2668
 foo5( cp );	//C2667,C2668
}

covariantの戻り値の型を持つ 仮想関数

class foo7_a {
public :
 virtual foo7_a* f( );
};
class foo7_b : public foo7_a {
public :
 //C2555
 foo7_b* f( );
};

ADLがoperator以外では動かない

namespace foo8 {
    struct T2 {
    };
    void g( T2 ) {
    }
    T2 operator+( T2 a, T2 b ) {
        std::cout << "in T2::+" << std::endl;
        return b;
    }
}
int main(int argc, char *argv[]){
 foo8::T2 t1, t2;
    
 // C2065 (引数型から関数を特定できない)
 g( t1 );
 t1 + t2;
}

テンプレートの部分特殊化

template<class T, int I> struct foo9 {    void f(){}; };
//C2989,C2988
template<class T> struct foo9<T,2> {};

多階層テンプレート

template<class T> class foo11_ {};
//C2954,C2951,C2226,C2143,C2059 (パースできねーよバーカみたいな)
template<class U, class V, template<class T> class C = foo11_>
class foo11 {
    C<U> key;
    C<V> value;
};

const void*を返す関数は怪しい

boostのソースより

boost/aligned_storage.hpp
// MSVC6 seems not to like inline functions with const void* returns, so we
// declare the following here:

らしいけどこれ本当なんでしょうか。出典求む

関数に対するoperator==

class Foo{
 const int A(){  return 1; };
 const bool B(){  return A()==0; }; //
 const bool C(){  return A==0; };  //VC6だとコンパイル通る
 const bool D(){  return A<0; }; //VC6でもNG
 const int E() {  return A=0; }; //VC6でもNG
 const int F() {  return A+1; }; //VC6でもNG
};

安直なgetterとかで

class Foo{
 int value;
 const int Value() const;
};

なんて使い方をしてる場合、()を抜くtypoをしてもVC6は教えてくれません

その他

std::timeって書くとコンパイルエラーとか2038年問題とかですかね

(2011/02/02追記)そういえば

これダメだった気がするけど今確認できない

template <unsigned char A>
void func(){}
対策
#define unsigned char UCHAR
template <UCHAR A>
void func(){}

(2011/02/03追記)iteratorに対するポインタのキャスト

以下のソースは、VC6で通ります

 std::vector<int> a(3);
 a.erase(&a[0]);

環境を変えるときには全部iteratorに書き直さないとダメ

(2011/02/17追記)enumと配列

以下のソースは、VC6で通りません

 enum { n = 5 };
 int a[n]={};

enumで確保も出来ないし{}で初期化もできない。

解決法

defineとmemsetにしましょう

 #define a_size_ (5)
 int a[a_size_]; memset(a,0,a_size_);

環境を変えるときには全部iteratorに書き直さないとダメ