![]() |
Home | Libraries | People | FAQ | More |
このページには Borland C++ version 5.5.1 コンパイラの言語機能についての、移植性のヒントが書かれている。更に、 Appendix には Borland C++ version 5.5 の追加の問題点が書かれている。 Borland C++ 5.5.1 は Win32 用のフリーのコマンドラインコンパイラであり、 http://www.borland.com/ から入手できる。
以下のリストの各項目では個々の問題を説明し、その作用を示すサンプルソースコードを付けている。ここのサンプルコードのほとんどは、 gcc 2.95.2 と Comeau C++ 4.2.44 でコンパイルできる事を確認している。
__BORLANDC__
が定義されている。このシンボルの値は、コンパイラのバージョン番号の 16 進表記になっている。以下の表に、判明している値を示す。
Compiler | __BORLANDC__ value |
---|---|
Borland C++ Builder 4 | 0x0540 |
Borland C++ Builder 5 | 0x0550 |
Borland C++ 5.5 | 0x0550 |
Borland C++ 5.5.1 | 0x0551 |
Borland C++ Builder 6 | 0x0560 |
using
指令と using
宣言の混在using
指令 (名前空間全体が対象) と名前空間レベルの using
宣言 (別の名前空間に属する個々の識別子が対象) を混合して使うと、実際には存在しない曖昧さが生じる。以下が、これを示すコードの一部である。[訳注1]
namespace N { int x(); } using N::x; using namespace N; int main() { &x; // 曖昧なオーバロード }
using
宣言using
宣言の引数として使える。しかし、以下のコードは Borland C++ でコンパイルできない。[訳注1]
template<class T> class X { }; namespace N { // "特化パラメータを使用しないとテンプレート 'X<T>' を使えない" using ::X; };
template<class T> void f(T x) { x = 1; // 大丈夫 (void) &x; T y = 17; y = 20; // "const オブジェクトは変更できない(関数 f<const int>(int) )" (void) &y; } int main() { const int i = 17; f(i); }boost/rational.hpp ヘッダの gcd() 関数関連で、これが問題になる。
template<class Arg> void f( void(*g)(Arg) ); void h(int); void h(double); template<class T> void h2(T); int main() { void (*p)(int) = h; // これは通る (std:13.4-1.1) void (*p2)(unsigned char) = h2; // これも通る (std:13.4-1.1) f<int>(h2); // これも通る (std:13.4-1.3) // "h(int) からテンプレート特化を生成できない", // "f<Arg>(void (*)(int)) に一致するものが見つからない" f<double>(h); // 通るべき (std:13.4-1.3) f( (void(*)(double))h); // C 形式のキャストは通る (std:13.4-1.6 with 5.4) // "このコンテキストではオーバロード 'h' が曖昧" f(static_cast<void(*)(double)>(h)); // 通るべき (std:13.4-1.6 with 5.2.9) }回避手段: オーバロードされた (されうる) 関数のアドレスの決定には、常に C 形式のキャストを使う。
const char *
から std::string
への変換const char *
型から std::string
型への暗黙の型変換が失敗する。 (ただし、普通のケースでは成功する) [訳注1]
#include <string> template<class T> void f(const std::string & s) {} int main() { f<double>("hello"); // "f<T>(char *) に一致するものが見つからない" }回避手段: テンプレート関数の明示的な実体化 (これには Microsoft Visual C++ で重大な問題がある) を避け、該当する型のデフォルトコンストラクトされた使用しないダミー引数を渡すようにする。明示的な実体化を使い続けたいならば、代わりに
std::string
への明示的な型変換を使うか、 const char *
型の引数を取るテンプレート関数を宣言する。
template<class T> struct A { static const bool value = true; }; // "テンプレートはクラスまたは関数でなければならない", "宣言の構文エラー" template<class T, bool v = A<T>::value> struct B {}; int main() { B<int> x; }回避手段: 関連する非型テンプレート引数が実装の詳細のものなら、継承と完全に限定された識別子を使う (例えば、 ::N::A<T>::value) 。
#include <iostream> template<class T> struct A {}; template<class T1> void f(const A<T1> &) { std::cout << "f(const A<T1>&)\n"; } template<class T> void f(T) { std::cout << "f(T)\n"; } int main() { A<double> a; f(a); // 出力: f(T) (誤) f(1); // 出力: f(T) (正) }回避手段: そのような関数全てを一律に、値の引数をとるか参照の引数をとるか、どちらか一方で宣言する。
template<class U> class C { }; template<class T> class A { static const int v = C<void (T::*)()>::value; };回避手段: 仲立ちとして
typedef
を使う。
template<class U> class C { }; template<class T> class A { typedef void (T::*my_type)(); static const int v = C<my_type>::value; };(David Abrahams 、 Fernando Cacciola 、 Peter Dimov と交換したメールから抜き出したものだ。実際には試していない。)
double std::abs(double)
が無いdouble std::abs(double)
が定義されているべきだが (std:26.5-5 [lib.c.math]) 、定義されていない。[訳注1]
#include <cmath> int main() { double (*p)(double) = std::abs; // エラー }
std::abs(5.1)
と書くと、警告無しで int std::abs(int)
が使われるので注意する事。
同じような注意事項が、全ての標準数学関数にも当てはまるようだ。 Borland C++ では、全ての標準数学関数の float
と long double
のオーバロードが提供されていない。
回避手段: 型のジェネリック性が必要ないなら、 std::fabs
を使う。
namespace N { template<class T> class A { // "f は 'N' のメンバではない(関数 main() )" friend bool f(T x, T y) { return x < y; } }; } int main() { N::A<int> a; }このテクニックは boost/operators.hpp で広く使われている。このケースではコンパイラの要求に従ってもうまくいかない。その結果、「 1 つのテンプレートを実体化する事で、たくさんのヘルパ関数を名前空間スコープで宣言する」方法が使えなくなるからだ。 BOOST_NO_OPERATORS_IN_NAMESPACE (BOOST_NO_INLINE_FRIENDS_IN_CLASS_TEMPLATES の方がこのケースに合っているかもしれない) を定義すると、この問題の回避手段がとられるが、それはまた別の問題を引き起こす。 [using-template] を参照。
[訳注1] Borland C++ 5.6 (Borland C++ Builder 6) では修正されているようだ。
[訳注2] f<double>(h)
の問題は Borland C++ 5.6 で修正されているようだ。
Japanese Translation Copyright © 2003 Hiroshi Ichikawa
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。