![]() |
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
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。