FAQ

QA・C/QA・C++

QA・C++ 特有のFAQに関するFAQ

Q「関数テンプレート・ボディの解釈を遅らせる(-dpft+)」オプションの設定基準を教えてください。 QA C++全バージョン

FAQ ID:3

A
コンパイラの中には、関数テンプレートの構文解析をテンプレートの インスタンスが作成される時点まで遅らせているものと、そうでない ものがあります。

お使いのコンパイラが、前者の挙動をする場合は、 「関数テンプレート・ボディの解釈を遅らせる(-dpft+)」オプション を設定する必要があります。後者の場合は、デフォルト(-dpft-)のまま にします。

具体的には、お使いのコンパイラが次のソースコードをエラーなく コンパイルできる場合は、-dpft+オプションを設定する必要があります。 // Error ==> -dpft- (default) // Success ==> -dpft+ class C { public: template <class T> void foo(){ u8 my_u8; } }; typedef unsigned int u8; void bar() { C c; c.foo<int>(); // Problem } int main(void) { return 0; }なお、設定方法は次の通りです。

GUIから設定する場合:
  [コンパイラ パーソナリティ] の [拡張] タブで
  [関数テンプレート・ボディの解釈を遅らせる]
  チェックボックスを選択します。

設定ファイルを直接編集する場合:
  -dpft+ と記述します。

回答を閉じる

Q「friend名を導く(-ifn+)」オプションの設定基準を教えてください。 QA C++全バージョン

FAQ ID:5

A
コンパイラの中には、friend宣言を前方宣言と同様に扱い、 friend宣言で使用された識別子を名前検索時に使用できる ようにしているものと、そうでないものがあります。

お使いのコンパイラが、前者の挙動をする場合は、 「friend名を導く(-ifn+)」オプション を設定する必要があります。後者の場合は、デフォルト(-ifn-)のまま にします。

具体的には、お使いのコンパイラが次のソースコードをエラーなく コンパイルできる場合は、-ifn+オプションを設定する必要があります。 // Error ==> -ifn- (default) // Success ==> -ifn+ class C { friend void foo(); }; void bar() { foo(); // Problem } void foo() {} int main(void) { return 0; }なお、設定方法は次の通りです。

回答を閉じる

Q「テンプレート・パラメータを反映(-ptp+)」オプションの設定基準を教えてください。 QA C++全バージョン

FAQ ID:2

A
コンパイラの中には、テンプレートの特殊化時に、その定義内で 特殊化元テンプレート定義のテンプレート・パラメータ名を 伝播して利用できるものと、そうでないものがあります。

お使いのコンパイラが、前者の挙動をする場合は、 「テンプレート・パラメータを反映(-ptp+)」オプション を設定する必要があります。後者の場合は、デフォルト(-ptp-)のままにします。

具体的には、お使いのコンパイラが次のソースコードをエラーなく コンパイルできる場合は、-ptp+オプションを設定する必要があります。 // Error ==> -ptp- (default) // Success ==> -ptp+ template <class T> class C { }; template <> class C<int> { T I; // Problem }; int main(void) { return 0; }なお、設定方法は次の通りです。

GUIから設定する場合:
  [コンパイラ パーソナリティ] の [拡張] タブで
  [テンプレート・パラメータを反映]
  チェックボックスを選択します。

設定ファイルを直接編集する場合:
  -ptp+ と記述します。

回答を閉じる

Q「依存基底クラスのルックアップ(-sdep+)」オプションの設定基準を教えてください。 QA C++全バージョン

FAQ ID:1

A
コンパイラの中には、識別子の名前検索(ルックアップ)の範囲をクラス・テンプレートの基底クラスにまで拡張するものと、そうでないものがあります。

お使いのコンパイラが、前者の挙動をする場合は、 「依存基底クラスのルックアップ(-sdep+)」オプション を設定する必要があります。後者の場合は、デフォルト(-sdep-)のままにします。

具体的には、お使いのコンパイラが次の ソースコードを エラーなくコンパイルできる場合は、-sdep+オプションを設定する必要があります。 // Error ==> -sdep- (default) // Success ==> -sdep+ template<typename T> struct U { typedef int result_type; }; template<typename T> class B : public U<T> { result_type fn(); // Problem }; int main(void) { return 0; }なお、設定方法は次の通りです。

GUIから設定する場合:
[コンパイラ パーソナリティ] の [拡張] タブで
[依存基底クラスのルックアップ]
チェックボックスを選択します。

設定ファイルを直接編集する場合:
-sdep+ と記述します。

回答を閉じる

Qconst enum { ... };という形式の構文は解析できないのでしょうか? QA・C++ の全バージョン

A
ISO C++違反の構文であるため解析することができません。理由は次の通りです。

クラス型、構造体型、共用体型、列挙体型は次の3種類の形式で定義することができます。1. タグのみを定義する形式 enum ENUM_TAG { enumerator1, enumerator2 };2. タグとオブジェクトを同時に定義する形式 enum ENUM_TAG { enumerator1, enumerator2 } enum_object;なお、2番目の形式は次と同等です。 enum ENUM_TAG { enumerator1, enumerator2 }; ENUM_TAG enum_object;3. タグとtypedef識別子を同時に定義する形式 typedef enum ENUM_TAG { enumerator1, enumerator2 } TYPEDEF_ENUM;なお、3番目の形式は次と同等です。 enum ENUM_TAG { enumerator1, enumerator2 }; typedef ENUM_TAG TYPEDEF_ENUM;1番目の形式は、タグを定義しているだけでオブジェクトやtypedef識別子を定義しているわけでは ありません。このため、ISO C++に準拠しているコンパイラでは、クラス型、 構造体型、共用体型、列挙型を表すそれぞれの キーワード class、struct、union、enum の前にオブジェクトを修飾するための キーワードを記述することはできません。
しかし、ISO C++に準拠していないコンパイラは、1番目の形式と1番目以外の形式を 適切に区別しないので次のような構文を記述できてしまいます。ISO C++違反の構文例1: const enum ENUM_TAG { enumerator1, enumerator2 };ISO C++違反の構文例2: virtual enum ENUM_TAG { enumerator1, enumerator2 };ISO C++違反の構文例3: static enum ENUM_TAG { enumerator1, enumerator2 };QA C++はISO C++に従ってこれらの構文をエラーとして扱います(該当箇所には14番の警告が出力されます)。
ISO C++に準拠していないコンパイラであっても1番目の形式では、キーワード class、struct、union、enum の前にオブジェクトを修飾するためのキーワードを記述した場合としなかった場合とで文法的な意味は変わらないはずなので、恐れ入りますが、ソースコード側を修正して解析できるようにしてください。

回答を閉じる

Qsizeof intという形式の構文は解析できないのでしょうか? QA・C++ の全バージョン

A
ISO C++違反の構文であるため解析することができません。理由は次の通りです。

sizeof演算子は次の3種類の形式で使用することができます。1. 括弧'()'を使ってオペランドに型名を与える形式 size_t size; size = sizeof(int);2. 括弧'()'を使ってオペランドにオブジェクト名を与える形式 int obj; size_t size; size = sizeof(obj);3. 括弧'()'を使わずにオペランドにオブジェクト名を与える形式 int obj; size_t size; size = sizeof obj;しかし、3番目の形式と似ていますが、次の形式は使用することができません。4. 括弧'()'を使わずにオペランドに型名を与える形式 int obj; size_t size; size = sizeof int;しかし、ISO C++に準拠していないコンパイラは、3番目の形式と4番目の形式を 適切に区別しないので4番目の形式の構文を記述できてしまいます。
QA C++はISO C++に従ってこの構文をエラーとして扱います(該当箇所には14番の警告が出力されます)。
ISO C++に準拠していないコンパイラであっても4番目の形式では、括弧'()'を記述しなかった場合と記述しなかった場合とで文法的な意味は変わらないので、恐れ入りますが、ソースコード側を修正して解析できるようにしてください。

回答を閉じる

Q#include < 空白 afxwin.h 空白 >という形式の構文は解析できないのでしょうか? QA・C++ の全バージョン

A
QA C++では解析することができません。理由は次の通りです。

QA C++は<>内に空白文字が記述されていた場合、空白文字をヘッダファイル名 の一部と見なして解析するようになっています。
また、コンパイラの中にはQA C++と同様の解釈をするようになっているものも あります(例えばGNU G++)。#include < iostream > // QA C++はヘッダファイルを見つけられない。#include <iostream> // QA C++はヘッダファイルを見つけられる。QA C++はこの構文をエラーとして扱います(該当箇所には34番の警告が出力されます)。
空白文字を記述した場合と記述しなかった場合とで文法的な意味は変わらないので、恐れ入りますが、ソースコード側を修正して解析できるようにしてください。

回答を閉じる

Qクラス定義の中以外に記述した friend class XXX; という形式の構文は解析できないのでしょうか? QA・C++ の全バージョン

A
ISO C++違反の構文であるため無視して解析されます。理由は次の通りです。

friend修飾子は、friend修飾子付きで宣言された関数やクラスに、 それらを包含するクラスのprivateやprotectedメンバへのアクセス権限 を与えるという役割を持ちます。
別の言い方をすると、friend修飾子は、friend修飾子付きで宣言された 関数やクラスと、それらを包含するクラスを結びつける役割を持って いることになります。
この役割が表す通り、friend修飾子は、クラス定義の中で記述される ことが前提になっています。
このため、次の構文はISO C++違反になります。 friend class CFriend; class CTest { public: void func(CFriend* p); }正しい構文は次の通りになります。 class CTest { friend class CFriend; public: void func(CFriend* p); }QA C++はISO C++に従って前者の構文をエラーとして扱います(該当箇所には254番の警告が出力されます)。
完全に不適切な構文になりますので、恐れ入りますが、ソースコード側を修正して解析できるようにしてください。

回答を閉じる

Q置換文字列内で##を使用しているマクロから同様のマクロを呼び出すと解析できないのでしょうか? QA・C++ の全バージョン

A
マクロの記述内容によっては、ISO C++違反の構文になるため解析することができません。

ISO C++言語規格書の16.3.4には次の規則が記されています。

オブジェクト形式マクロ 及び 関数形式マクロのいずれの呼出しにおいても, その置換内容列を再検査して, 更に置き換えるべきマクロ名があるかどうか を調べる前に, 置換内容列中の各前処理字句## (実引数からもたらされた 前処理字句 ## は除く。) の出現を削除し, その直後にある前処理字句と その直後の前処理字句とを連結する。例えば、次のようなコードを記述した場合、 #define MACRO1(x) func(data_ ## x) #define MACRO2(y) MACRO1(## y ##) #define ONE 1 void func(int x) {} int main(void) { int data_1 = 1; MACRO2(ONE); return 0; }MACRO2の展開結果は、data_1 にはなりません。MACRO2の展開結果は、data_ONE になります。これは、MACRO1とMACRO2の両方のマクロが、置換文字列内で##を使用し、 MACRO2がMACRO1を呼び出しているので、ISO C++に従った場合、 ONEが独立したマクロとして認識されるよりも前に、 data_ONEという文字列が生成されるからです。
QA C++はISO C++に従って解析し、MACRO2(ONE) を data_ONE に展開するので、 上記のコードをエラーとして扱います (該当箇所には400番の警告が出力されます)。
本問題に遭遇した場合は、恐れ入りますが、適宜回避策があるかどうかを ご相談ください。
なお、上記のコードの場合は、 「MACRO1(## y ##) → MACRO1(y)」に記述し直すことができれば、 ISO C++に従った構文になるので、QA C++が正しく解析できるようになります。

回答を閉じる

Q変数名に and や or を使用すると解析できないのでしょうか? QA・C++ の全バージョン

A
ISO C++違反の構文であるため解析することができません。理由は次の通りです。

ISO C++言語規格書の2.5-2には次のように記されています。

代替字句は, その綴りの違いを除いて, 言語のすべての面で, 正規字句と完全に 同等に振る舞う。代替字句は, 表2に示すとおりとする。表2 代替字句
 代替   正規   代替   正規 
 and   &&   and_eq   &= 
 bitor   |   or_eq   |= 
 or   ||   xor_eq   ^= 
 xor   ^   not   ! 
 compl   ~   not_eq   != 
 bitand   &     

一般的には"正規"欄に記述された字句を使用しますが、 C++ではこれらの字句の代わりに、"代替"欄に記述された字句を使用 することができます。具体的には、一般的に次のように記述するコードを void func(int a, int b) { if( a && b ) { } }次のように記述することができます。 void func(int a, int b) { if( a and b ) { } }このように、ISO C++では代替字句が正規字句と完全に同等に振る舞うことを 要求しているので、これらの代替字句を変数名や関数名の代わりに 使用することはできません。例: void func(void) { int and; // C++では int &&と同等 }QA C++はISO C++に従って解析するので、上記の構文をエラー として扱います(該当箇所には14番の警告などが出力されます)。
恐れ入りますが、代替字句を変数名や関数名として使用している場合は、 名称を変更して解析できるようにしてください。

回答を閉じる

Q<列挙体名>::<列挙子名>; という形式の構文は解析できないのでしょうか? QAC++2.3.1J以下

A
ISO C++違反の構文であるため解析することができません。ただし、QAC++2.3.1Jの次バージョンからは解析することができます。理由は次の通りです。

ISO C++言語規格書の7.2-10には次のように記されています。

<<列挙体名>> 及び 列挙体指定子によって宣言された各列挙子は, その列挙体 指定子を直接に含む有効範囲の中で宣言される。これらの名前は, すべての 名前に対する有効範囲規則(3.3及び3.4参照)に従う。クラス有効範囲内で 宣言された列挙子は, そのクラスのメンバアクセス演算子(::, . 及び ->) を使って参照することができる(5.2.5参照)。具体的には、次のようなクラスと列挙体を定義した場合、 class CTest { public: enum ENUM_TEST { ETEST1, ETEST2 }; };次の構文は正しい構文になります。 void func1(void) { CTest::ENUM_TEST ent = CTest::ETEST1; }しかし、列挙体名(ENUM_TEST)は有効範囲を構成する要素には成り得ないので、次の構文は間違った構文になります(赤太字の部分が問題です)。 void func2(void) { CTest::ENUM_TEST ent = CTest::ENUM_TEST::ETEST1; }QA C++はISO C++に従って前者の構文をエラーとして扱います(該当箇所には400番の警告が出力されます)。
"<列挙体名>::"を記述した場合と記述しなかった場合とで文法的な意味は変わらないので、恐れ入りますが、ソースコード側を修正して解析できるようにしてください。

回答を閉じる

Q#if defined(new)という形式の構文は解析できないのでしょうか? QAC++2.1J以下

A
QAC++2.3.1J以降では解析することができます。

C++言語で、new は予約語になっています。
このため、defined演算子の識別子に new 与えることはできません。#if defined(new)// ...#endifしかし、ISO C++に準拠していないコンパイラは、この構文を記述できてしまいます。
バージョン2.1J以前のQA C++はISO C++に従ってこの構文をエラーとして扱います(該当箇所には22番の警告が出力されます)が、バージョン2.3.1J以上のQAC++は機能拡張してこの構文をエラー扱いしないようになっています。

回答を閉じる