RAD Studio の Clang 拡張 C++ コンパイラでサポートされている Modern C++ 機能

提供: RAD Studio
移動先: 案内検索

Modern C++ への移動


メモ: RAD Studio は C++11 および C++14 をサポートしていますが、コンパイル時に問題が発生する可能性があります。

目次

Clang 拡張 C++ コンパイラでサポートされている C++17 機能

Win32/Win64 用 Clang 拡張コンパイラ(bcc32c/bcc32x/bcc64)は、ISO C++17 標準のほぼすべてを実装しています。

メモ: どの C++ 17 機能が各 RAD Studio のC++ コンパイラでサポートされているかについては、モダン C++ 言語機能の準拠状況 を参照してください。

C++17 の興味深い機能には、次のものがあります:

  • constexpr if - コンパイル時の式への大きな追加です。
  • string_view - コピーしない(つまり、低コストかつ高速)文字列型のバリエーションへの読み取り専用アクセスのための便利な追加機能
  • if-init (if 文での変数の初期化)
  • 構造型のバインディング.
  • インライン変数

C++17 の詳細については:

Clang 拡張 C++ コンパイラでサポートされている C++14 機能

Win32/Win64 用 Clang 拡張コンパイラ(bcc32c/bcc32x/bcc64)は、ISO C++14 標準のほぼすべてを実装しています。

メモ: どの C++14 機能が各 RAD Studio のC++ コンパイラでサポートされているかについては、モダン C++ 言語機能の準拠状況 を参照してください。

C++14 の興味深い機能には、次のものがあります:

  • auto での戻り値型の軽減
  • 汎用パラメータとのラムダ式(auto を介する)
  • 変数テンプレート

C++14 の詳細については:

Clang 拡張 C++ コンパイラでサポートされている C++11 機能

RAD Studio の Clang 拡張 C++ コンパイラ でサポートされている C++11 機能の一覧を以下に示します。

メモ: どの C++11 機能が各 RAD Studio のC++ コンパイラでサポートされているかについては、モダン C++ 言語機能の準拠状況 を参照してください。
  • Bcc32c および bcc32x(Win32 用 Clang 拡張 C++ コンパイラ)では、ISO C++11 標準 すべてを実装しています。
  • 旧式の Clang 拡張 C++ コンパイラは、C++11 機能を一部サポートしています:
    • コア C++11 機能は通常、BCCIOSARM64 で動作します。 これには、可変個引数テンプレート、静的アサーション、多重宣言子形式の auto、ラムダ式などが含まれます。
    • 標準(実行時)C++11 機能は通常、BCCIOSARM64 ではサポートされていません。 これには、右辺値によるクラス オブジェクトの初期化、アトミック操作などが含まれます。
  • BCC32 はまた C++11 機能 もサポートしており、これについては、「クラシック コンパイラでの C++11 機能」に記載されています。
メモ: C++11 に固有のキーワード(nullptrnoexcept など。全一覧はこちら http://en.cppreference.com/w/cpp/keyword)を使用する場合、RAD Studio IDE は常にこれらのキーワードを認識しますが、C++ の旧世代のコンパイラ(BCC32)はコンパイル エラーを返します。Clang 拡張 C++ コンパイラのみが C++11 標準をサポートしている点に注意してください。

右辺値参照

右辺値参照は、BCC32 と Clang 拡張 C++ コンパイラでサポートされている機能です。

この機能の詳細については、「右辺値参照」を参照してください。

*this の右辺値参照

*this の右辺値参照は、移動セマンティクスの利点を暗黙の *this パラメータに広げることを目的とした C++11 機能です。

この機能の詳細については、*this の右辺値参照に関する提案書を参照してください。

右辺値によるクラス オブジェクトの初期化

C++11 標準では、明快で簡潔かつ効率的なコードを作成できるように、右辺値でクラス オブジェクトを初期化できるようになっています。

つまり、コンストラクタを呼び出してオブジェクトを一時変数にコピーするのではなく、一時変数が右辺値オブジェクト全体から直接初期化されるようになりました。

この機能の詳細については、右辺値によるクラス オブジェクトの初期化に関する提案書を参照してください。

非静的データ メンバ初期化子

C++11 では、クラス宣言内で非静的データ メンバを初期化できるようになっています。

非静的データ メンバの初期化子は =initializer-clause{initializer-list} に限定されます。

この機能の詳細については、以下の例や「非静的データ メンバ初期化子に関する提案書」を参照してください。

非静的データ メンバ初期化子の例

#include <string>

struct B {
        B(int, double, double);
};

class A {
        int a = 7; // OK
        std::string str1 = "member"; // OK
        B b = {1, 2, 3.0}; //OK
        std::string str2("member");   // ill-formed
};

可変個引数テンプレート

可変個引数テンプレートとは、取り得るパラメータの個数が可変のクラス テンプレートまたは関数テンプレートのことです。

これを実現するため、C++11 には、ゼロ個以上のパラメータのリストを表すパラメータ パックが導入されています。

この機能の詳細については、可変個引数テンプレートに関する提案書を参照してください。

可変個引数テンプレートの例

以下は、可変個引数テンプレートの C++ 構文を示す簡単な例です。

template<class ... T>
class A {
        // template class body
};

template<char ... T>
class B {
        // template class body
};

A<>a1;
A<int, char>a2;
A < B < 'a' >> a3;

B<>b1;
B < 'a', 'b' > b2;

可変個引数テンプレートのテンプレート パラメータの拡張

可変個引数テンプレートを実際に試す中で、テンプレートのテンプレート パラメータに関する制限事項がいくつか明らかになりました。

C++11 標準では、この問題点を解決するために可変個引数テンプレートのテンプレート パラメータを拡張しています。

この機能の詳細については、可変個引数テンプレートのテンプレート パラメータの拡張に関する提案書を参照してください。

初期化リスト

初期化リストは、C++11 標準で拡張された機能です。

初期化リストは、順序付き引数のリストを中かっこで囲んだものを表し、構造体、クラス、配列の初期化に使用されます。
C++11 までは、POD(Plain Old Data: 従来の普通のデータ)定義に準拠するクラスのみ、初期化リストを使って初期化できました。 現在では、std::vector のようなクラスも、初期化リストを使って初期化できます。 これは、コンストラクタやその他の関数に引数として渡せる std::initializer_list<> というテンプレートを使って行われます。

静的アサーション

静的アサーションは、BCC32 と Clang 拡張 C++ コンパイラでサポートされている機能です。

この機能の詳細については、「静的アサーション(C++11)」を参照してください。

自動型指定変数

自動型指定変数は、プログラムで auto 型の変数を宣言できる C++11 の機能です(型そのものは変数の初期化子式から推測されます)。auto keyword は単純型指定子として扱われ(*& と一緒に使用可能)、その意味は初期化子の式から推測されます。

この機能の詳細については、C++11標準規格の「自動型指定変数に関する提案書」を参照してください。

自動型指定変数の例

int IntFunc() {}
bool BoolFunc() {}
char* CharSFunc() {}

int _tmain(int argc, _TCHAR* argv[]) {
        // x is int
        auto x = IntFunc();
        // y is const bool
        const auto y = BoolFunc();
        // w is char*
        auto w = CharSFunc();
        return 0;
}

auto 型の他の例はこちらから: ジェネリック ベクタのソート (C++)

多重宣言子 auto

C++11 標準では、次のような、auto 宣言の複数変数形式が含まれています:

int* func(){}

int _tmain(int argc, _TCHAR* argv[])
{
        auto x = 3, * y = func(), z = 4;
        return 0;
}

多重宣言子形式の auto 式には、変数の基底型が同じでなければならないという制限事項があります。

たとえば、以下のコードは正しい形式です。

auto x = 3, y = new int;

それは、x と y の基底型が同じ(int)だからですが、それに対して、以下のコードでは、 

auto x = 3, y = 3.5;

[bcc64 エラー] File1.cpp(11): 'auto' が、'x' の宣言では 'int' と、'y' の宣言では 'double' と推定されます」というエラーが発生します。

この機能は Clang 拡張 C++ コンパイラでサポートされています。

この機能の詳細については、C++11 標準規格の多重宣言子形式の auto に関する提案書を参照してください。

記憶クラス指定子としての auto の削除

C++11 標準では、auto が記憶クラス指定子としてまったく使用されなくなりました。 この機能は Clang 拡張 C++ コンパイラでサポートされています。

C++ アプリケーションで auto を記憶クラス指定子として使用している場合は、Clang 拡張 C++ コンパイラから以下の警告が出力されます。

テンプレート:警告

この機能の詳細については、C++11 標準規格の 記憶クラス指定子としての auto の削除 に関する提案書を参照してください。

関数宣言子の新しい構文

この C++11 機能では、auto のセマンティクスを変更し、関数宣言子の新しい構文を導入しています。 型指定子 auto は、宣言している変数の型が初期化子式から推測されるか、関数宣言子の末尾で明示的に指定されることを示します。

この機能の詳細については、C++11 標準規格の 関数宣言子の新しい構文 に関する提案書を参照してください。 

式の宣言された型

式の宣言された型は、BCC32 と Clang 拡張 C++ コンパイラでサポートされている機能です。

この機能の詳細については、「指定子 decltype (C++11)」を参照してください。

不完全な戻り値型

decltype のパラメータとして使用する際に関数呼び出し式の型は完全でなければならないという要件は、不必要なだけではなく、有害でもあります。

C++11 では、decltype 式のパラメータが、クラス型を返す関数呼び出し式である場合、その型は完全でなくてもかまいません。 さらに、戻り値用の一時オブジェクトは導入されず、記憶領域が節約されると共にデストラクタが呼び出されません。

この機能の詳細については、不完全な戻り値型に関する提案書を参照してください。

右山かっこ

Clang 拡張 C++ コンパイラでは、連続する 2 つの右山かっこがあっても、もうエラーは発生せず、これらの構文要素は C++11 標準に従って扱われます。

詳細については、C++11 の右山かっこに関する提案書を参照してください。

右山かっこの例

#pragma hdrstop
#pragma argsused

#include <tchar.h>
#include <stdio.h>

#include <vector>
typedef std::vector<std::vector<int> > Table;  // OK
typedef std::vector<std::vector<bool>> Flags;  // OK

int _tmain(int argc, _TCHAR* argv[]) {

        return 0;
}

関数テンプレートのデフォルト テンプレート引数

関数テンプレートのデフォルト テンプレート引数を設定できなかったため、プログラミング スタイルは長い間制限されてきました。

C++11 では、このようなデフォルト引数を使用できます。

この機能の詳細については、関数テンプレートのデフォルト テンプレート引数に関する提案書を参照してください。

関数テンプレートのデフォルト テンプレート引数の例

template<class T = int, class U = char>
void function() {
        // function body
}

int _tmain(int argc, _TCHAR* argv[]) {
        function<>();            // OK, template arguments are -> int char
        function<int>();         // OK, template arguments are -> char
        function<char, char>();  // OK, template arguments are -> char char
        return 0;
}

式の SFINAE 問題の解決

C++11 標準では、式の SFINAE(Substitution Failure Is Not An Error: 置換の失敗はエラーにならない)問題が解決されています。 これは、これらの式で発生する大半のエラーをエラーではなく SFINAE 関連の失敗として扱うという条件で完全に一般的な式を使用可能にすることにより実現されています。

この機能の詳細については、式の SFINAE 問題の解決に関する提案書を参照してください。

エイリアス テンプレート

C++ でパラメータ化型が使用される場合が増えてきたことで、パラメータ化型エイリアスの必要性が高まってきました。 C++11 では、この機能が標準に追加されています。

この機能の詳細については、「エイリアス テンプレートに関する提案書」を参照してください。

extern テンプレート

extern テンプレートは、BCC32 と Clang 拡張 C++ コンパイラでサポートされている機能です。

この機能の詳細については、「extern テンプレート(C++11)」を参照してください。

null ポインタ定数

C++11 には、0 と null ポインタの間のあいまいさをなくすため、null ポインタ定数である nullptr が導入されています。

NULL マクロは存在しますが、int パラメータを持つオーバーロードと char* パラメータを持つもう 1 つのオーバーロードを持つ関数の呼び出しで整数 0 と区別できないため、それでは不十分です。

そのため、nullptr が予約語になりました。 整数 0 は、どのようなポインタ型にも暗黙的に変換されません。 null ポインタのみ任意のポインタ型に変換できます。

メモ: null ポインタは、算術式で使用することも、整数値に代入することも、整数値と比較することもできません。
メモ: 詳細については、null ポインタ定数に関する提案書を参照してください。

nullptr」を参照してください。

厳密に型指定された列挙型

厳密に型指定された列挙型は、BCC32 と Clang 拡張 C++ コンパイラでサポートされている機能です。

この機能の詳細については、「厳密な型指定の列挙型(C++11)」を参照してください。

列挙型の前方宣言

列挙型の前方宣言は、BCC32 と Clang 拡張 C++ コンパイラでサポートされている機能です。

この機能の詳細については、「列挙型の前方宣言(C++11)」を参照してください。

一般化された定数式

C++11 標準では、定数式の概念が一般化され、単純な関数(constexpr 指定された関数)の呼び出しや単純なコンストラクタ(constexpr 指定されたコンストラクタ)で生成されるユーザー定義型のオブジェクトも定数式に含まれます。

以下の場合、関数は定数式関数です。

  • 値を返す(void 型は不可)。
  • 関数本体は 1 つの文、return 文から構成される (return expr;
  • キーワード constexpr を付けて宣言されている。

以下の場合、変数またはデータ メンバは定数式値です。

  • キーワード constexpr を付けて宣言されている。
  • 定数式で初期化されているか、定数式引数を持つ定数式コンストラクタで生成される右辺値で初期化されている。

以下の場合、コンストラクタは定数式コンストラクタです。

  • キーワード constexpr を付けて宣言されている。
  • メンバ初期化子の部分に、定数式の可能性があるもののみ含まれている。
  • 本体が空である。

一般化された定数式の例

以下の例には、constexpr 指定の関数、constexpr 指定の変数、constexpr 指定のコンストラクタが含まれています。

constexpr int add(int x, int y) {
        return x + y;
}
constexpr double var = 2 * add(3, 4);

class A {
        constexpr A(int newA, int newB) : a(newA), b(newB) {
        }

private:
        int a;
        int b;
};

アラインメント サポート

C++11 標準では、アラインメント関連機能を付加して標準言語およびライブラリを拡張しようとしています。

これらのアラインメント機能は以下のとおりです。

  • 宣言に対するアラインメント指定子(alignas
  • 型のアラインメント要件を取得するための alignof
  • ライブラリ サポートによるアラインメント計算
  • 実行時におけるポインタ アラインメントのための標準関数(std::align

この機能の詳細については、アラインメント サポートに関する提案書を参照してください。

委譲コンストラクタ

C++11 では、委譲コンストラクタを使用できるようになっています。 つまり、クラス コンストラクタを同じクラスの他のコンストラクタの中で呼び出すことができます。

これは、作成するコードの量を減らしつつ表現力を高めるのに役立つ非常に有用な機能です。

この機能の詳細については、委譲コンストラクタに関する提案書を参照してください。

委譲コンストラクタの例

以下の例では、委譲コンストラクタの使用方法を示しています。

class B {
        B(int newA) : a(newA) { /* other initializations */
        }

public:
        B() : B(15) { /* other initializations */
        }

public:
        int a;
};

明示的な変換演算子

C++11 では、明示修飾された変換関数は明示修飾されたコンストラクタと同じコンテキストで動作し、コンストラクタと同じコンテキストで診断情報を生成します。 これは、セマンティクス上正しくないコードをコンパイラがエラーや警告を出力せずに通してしまうような状況を避けるためです。

この機能の詳細については、明示的な変換演算子に関する提案書を参照してください。

新しい文字型

C++11 には、Unicode 文字の文字列を操作するための新しい文字型が導入されています。

この機能の詳細については、「Unicode 文字型とリテラル(C++11)」を参照してください。

Unicode 文字列リテラル

C++11 には、Unicode 文字列リテラルを操作するための新しい文字型が導入されています。

この機能の詳細については、「Unicode 文字型とリテラル(C++11)」を参照してください。

生の文字列リテラル

リテラル内の汎用文字名

C++ コードのプラットフォーム依存性を減らすため、C++11 では、制御文字および基本ソース文字を表す汎用文字名を文字リテラルおよび文字列リテラル内で使用できるようになりました(これまで、これらの使用は禁止されていました)。 一方、すべての汎用文字名でサロゲート値を使用できなくなりました。

この機能の詳細については、リテラル内の汎用文字名に関する提案書を参照してください。

ユーザー定義リテラル

C++11 には、ユーザー定義リテラルを提供できるように、変更された構文とセマンティクスを用いた新しい形式のリテラルが導入されています。

ユーザー定義リテラルを使用すると、ユーザー定義クラスで新しいリテラル構文を提供できます。

この機能の詳細については、ユーザー定義リテラルに関する提案書を参照してください。

標準レイアウト型

C++11 では、よりすっきりした仕様にするため、レイアウト要件から自明な特殊メンバの要件が切り離されています。

POD(Plain Old Data: 従来の普通のデータ)型は、自明型と標準レイアウト型という、2 つの新しいカテゴリに基づいて定義されるようになりました: C++11 の標準レイアウト型は基底クラスを持つことができます。 ただし、それらの基底クラスは仮想メンバや仮想基底を持てません。 また、標準レイアウト型はアクセス制御が可能です。

この機能の詳細については、標準レイアウト型に関する提案書を参照してください。

デフォルト定義関数

デフォルト定義関数は、プロトタイプに =default; が含まれている関数です。 この構文要素は、関数のデフォルト定義が使用されることを示しています。

デフォルト定義関数は C++11 固有の機能です。

この機能の詳細については、デフォルト定義関数に関する提案書を参照してください。

デフォルト定義関数の例

class A {
        A() = default;                    // OK
        A& operator = (A & a) = default;  // OK
        void f() = default;               // ill-formed, only special member function may default
};

削除済み関数

削除済み関数は、プロトタイプに =delete; が含まれている関数です。 この構文要素は C++11 で導入されたもので、その関数を使用してはいけないことを示します。

この構文要素を使用すると、(デフォルト コンストラクタやデフォルト演算子のような)デフォルトの言語機能や問題のある変換を使用できなくすることが可能です。

この機能の詳細については、削除済み関数に関する提案書を参照してください。

削除済み関数の例

class A {
        A() = delete;
        A& operator = (A & a) = delete;
};

拡張フレンド宣言

C++11 では、現在の言語を拡張して、さまざまな friend 宣言をサポートしています。

この機能の詳細については、拡張フレンド宣言に関する提案書を参照してください。

sizeof の拡張

C++11 では、オブジェクトがインスタンス化されていなくてもクラス メンバをパラメータとして渡せるように、sizeof の機能が拡張されています。

この機能の詳細については、sizeof の拡張に関する提案書を参照してください。

sizeof の拡張の例

以下のコードは、sizeof の現在の使用方法を示す簡単な例を表しています。

#pragma hdrstop
#pragma argsused

#include <tchar.h>
#include <stdio.h>

class A {
public:
        int a;
};

int _tmain(int argc, _TCHAR* argv[]) {
        // no object of type A has been instantiated
        int c = sizeof(A::a);
        // well-formed
        return 0;
}

インライン名前空間

C++11 標準では、名前空間の定義(namespace-definition)で inline キーワードを使用できるようになっています。 これは、あたかも実際には外側の名前空間に属しているかのように名前空間のメンバを定義し特殊化できることを指定するためです。

この構文要素はインライン名前空間と呼ばれ、テンプレートの特殊化がインポート先の名前空間ではなく実際の名前空間でのみ可能であった問題を解決します。

この機能の詳細については、インライン名前空間に関する提案書を参照してください。

無制限共用体

C++11 標準では、共用体のメンバに関する制限が緩和されています。 そのため、Clang 拡張 C++ コンパイラでは、参照型以外のあらゆる型を共用体のメンバにすることができます。

この機能の詳細については、無制限共用体に関する提案書を参照してください。

テンプレート引数としてのローカル型および無名型

C++11 標準では、ユーザーはローカル型および無名型をテンプレート引数として使用できるようになっています。

この機能の詳細については、テンプレート引数としてのローカル型および無名型に関する提案書を参照してください。

範囲ベースの for

範囲ベースの for は、C++11 標準で導入された機能です。

Clang 拡張 C++ コンパイラでは、開始位置と終了位置を計算せずに、あるいはイテレータを使用せずに、リストや配列の要素を順に処理する for ループを作成できます。

以下の例では、文字列に対する範囲ベースの for の構文を示しています:

UnicodeString string("C++11");
for (auto character : string) {
    std::wcout << character;		
}

明示的な仮想オーバーライド

C++11 では、仮想オーバーライドに関しては、よく起こるいくつかの問題を検出できるようにルールを厳しくしている傾向があります。

この目標を達成するため、C++11 には以下の 2 つのコンテキスト キーワードが新たに導入されています。

  • final は、メソッドをオーバーライドできないこと、またはクラスが派生できないことを指定します。
  • override は、親クラスのいずれか 1 つで宣言されている仮想メソッドをメソッドがオーバーライドしていることを指定します。

この機能の詳細については、明示的な仮想オーバーライドに関する提案書を参照してください。

明示的な仮想オーバーライドの例

struct base {
        virtual void a();
        void b();
        virtual void c() final;
        virtual void d();
};

struct derived : base {
        void a() override; // correct
        void b() override; // error, an override can only be used for virtual functions
        void c() override; // error, cannot override a function marked as final
        int d() override; // error, different return type
};

移動コンストラクタで例外を送出可能 [noexcept]

C++11 標準には、移動コンストラクタ、テンプレート、一部の標準ライブラリ メンバ関数の間のやり取りにおける問題を解決するため、std::move の代わりとなるもの(std::move_if_noexcept)が用意されています。

std::move_if_noexcept(x) では、例外が送出される可能性があり型がコピー可能である場合を除いて、x の移動を許可します。

この機能の詳細については、移動コンストラクタでの例外の送出に関する提案書を参照してください。

移動用の特殊なメンバ関数の定義

C++11 には、移動用およびコピー用の特殊なメンバ関数を定義する手段が用意されています。

この機能の詳細については、移動用の特殊なメンバ関数の定義に関する提案書を参照してください。

アトミック操作

C++11 では、アトミック型とアトミック操作が標準に追加されています。 アトミック型とアトミック操作は、ロックを使用せずにマルチスレッド アプリケーションを作成する手段となります。

この機能の詳細については、アトミック操作に関する提案書を参照してください。

厳密な比較および交換

C++11 には、弱い比較および交換操作と厳密な比較および交換操作が両方とも用意されています。

比較および交換操作は、マルチスレッド アプリケーションで同期を実現するために使用されるアトミック操作です。

この機能の詳細については、厳密な比較および交換に関する提案書を参照してください。

双方向フェンス

フェンスは、先行するロードまたはストアと後続のロードまたはストアの間の順序付けを実行するプリミティブです。 C++11 では、双方向フェンスのサポートが強化されています。

この機能の詳細については、双方向フェンスに関する提案書を参照してください。

例外の伝播

C++11 標準では、スレッド間で例外を移動することができます。 それを実現するため、<exception> ヘッダーに少し変更が加えられました。

この機能の詳細については、例外の伝播に関する提案書を参照してください。

シグナル ハンドラでアトミック操作を使用可能

C++11 では、シグナル ハンドラでアトミック操作を使用できるようになっています。

この機能の詳細については、シグナル ハンドラでのアトミック操作の使用に関する提案書を参照してください。

定義済み識別子 __func__

この機能は、関数名の文字列リテラルとしての取得と診断ライブラリの支援に使用されます。

この機能の詳細については、定義済み識別子 __func__ に関する提案書を参照してください。

C99 プリプロセッサ

C++11 標準では、C++ と C99 という 2 つの標準の互換性を高めるため、C++ のプリプロセッサ フェーズおよびトランスレーション フェーズを C99 と再度合わせようとしています。

変更が加えられた分野には、定義済みマクロ、プラグマ演算子、文字列リテラル連結などがあります。

この機能の詳細については、C99 プリプロセッサに関する提案書を参照してください。

long long 型

C99 との互換性を高めるため、C++11 標準には long long 整数型が導入されています。

この機能の詳細については、long long 型に関する提案書を参照してください。

その他の機能

関連項目