原文:
http://www.boost.org/more/microsoft_vcpp.html
![]() |
Home | Libraries | People | FAQ | More |
次のリスト中の各見出しは、結果を実証するサンプル ソース コードで完結する個々の問題点に関して述べている。 ここにあるほとんどのサンプル コードは、gcc 2.95.2 と Comeau C++ 4.2.44 でのコンパイルが確認されている。
_MSC_VER というプリプロセッサのシンボルが定義されている。その値は、コンパイラの内部的なバージョン番号の十進表記になっている。他のいくつかのコンパイラもこのシンボルを定義しているため、boost は、 もしコンパイラが本当に Microsoft Visual C++ であるときに限り、_MSC_VER の値として boost/config.hpp の中で定義されるシンボル BOOST_MSVC を用意している。
以下の一覧表に判明している値を示す。
| コンパイラ | BOOST_MSVC の値 |
|---|---|
| Microsoft Visual C++ 6.0 (SP4 まで) | 1200 |
using-declarationsusing 宣言が機能しない。
void f();
namespace N {
using ::f;
}
void g()
{
using N::f; // C2873: 'f': シンボルを using 宣言の中で使用することはできません。
}
#include <stdio.h>
template<class T>
void f()
{
printf("%d\n", sizeof(T));
}
int main()
{
f<double>(); // 出力: "1"
f<char>(); // 出力: "1"
return 0;
}
for ループ内における変数定義のスコープは、ループの内部だけのローカルなものであるべきなのに、そうでなく一つ外側のブロックでローカルになっている。
int main()
{
for(int i = 0; i < 5; ++i)
;
for(int i = 0; i < 5; ++i) // C2374: 'i': 再定義されています。2 回以上初期化されています。
;
return 0;
}
回避手段: 問題となる for ループをもう一つの別の一組の中括弧で囲う.
もう一つの可能な回避手段 (Vesa Karvonen が気付かせてくれた) は次のようなものである。
#ifndef for
#define for if (0) {} else for
#endif
インクルードされたヘッダー内のプラットフォーム依存のインライン関数が、古い形式の for のスコープに依存するかも知れないことに注意。
std::numeric_limits テンプレートの実装に必要な、クラス内でのメンバーの初期化がうまく機能しない。
struct A
{
static const int i = 5; // "純粋仮想関数の宣言に構文上の誤りがあります。"
};
回避手段: enum (正しい型とは言えないがコンパイル時に使用できる定数式) を使用するか、またはクラスの外側 (正しい型を使えるがコンパイル時の定数式として使うことは禁止) で定義する。boost ライブラリ中で、どうやって移植性の高いやり方でメンバーとして定数を定義するかのガイドラインを知るには、Coding Guidelines for Integral Constant Expressions を見ること。
namespace N {
struct A {};
void f(A);
}
void g()
{
N::A a;
f(a); // 'f': 定義されていない識別子です。
}
template<class T>
struct A {};
struct B
{
template<class T>
friend struct A; // "構文エラー"
};
template<class T>
struct A
{
template<class U>
void f();
};
template<class T>
template<class U> // "構文エラー"
void A<T>::f() // "T: 定義されていない識別子です。"
{
}
回避手段: メンバーのテンプレートを属するクラス内にインラインで定義する。
template<class T>
struct A {};
template<class T>
struct B {};
template<class T>
struct A<B<T> > {}; // このテンプレート クラスはすでに非テンプレート クラスとして定義されています。
回避手段: インタフェイスが重要でない状況では、クラスのメンバーのテンプレートが部分的な特殊化版をシミュレートできることがある。
template<class T, typename T::result_type> // C1001: 内部コンパイラ エラー: msc1.cpp, line 1794
struct B {};
// (omit "typename" and it compiles)
回避手段: "typename" キーワードを使うのを止める。しかしながら、こうすることでそのプログラムは正当であることが保障されなくなる。
wchar_t is not built-inwchar_t が組み込み型ではない。
wchar_t x; // "識別名を宣言するのに、型が指定されていません。"回避手段: Microsoft Visual C++ を使うときには、 boost/config.hpp ヘッダーは、wchar_t を unsigned short として typedef する形で定義している
<cstddef> をインクルードする。特記しておくと、このことは、コンパイラが wchar_t と unsigned short を、標準では別々の型であることが要求されるのに、別々の型とはみなさず、それゆえ wchar_t を使ってオーバーロードを行った場合には曖昧さが生じる、ということを意味するのである。この状況のときは BOOST_NO_INTRINSIC_WCHAR_T マクロが定義される。
const X * does not work
void f()
{
const int *p = new int(5);
delete p; // C2664: 'const int *' から 'void *' に変換できません。
}
回避手段: 以下のような関数を定義する。
inline void operator delete(const void *p) throw()
{ operator delete(const_cast<void*>(p)); }
それから、operator delete[] 等、std::nothrow な const や volatile 修飾子との結合のための同様の関数。
<c...> ヘッダーのライブラリの名前は、std 名前空間ではなくグローバルな名前空間におかれている。
回避手段: boost/config.hpp ヘッダーでは BOOST_NO_STDC_NAMESPACE を定義する。それは次のように使うことができる。
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::abs; using ::fabs; }
# endif
std::size_t と std::ptrdiff_t は余りに一般的に使われるので、これらのための回避手段は既に boost/config.hpp の中に用意されている。
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。