Qtプログラマー向けC ++ 14

この記事では、C ++ 14標準によってもたらされた変更がQtアプリケーションの開発にどのように影響するか、または影響する可能性があるかについて説明します。 この記事は、Qtプログラマーだけでなく、C ++の開発に関心のあるすべての人々にも焦点を当てています。 原作者は、Qt moc(メタオブジェクトコンパイラ)の開発者の1人であるOlivier Goffartです。





一般化されたラムダ関数



Lambda関数はC ++ 11で導入され、Qt5ではシグナルで使用できます。 C ++ 14では、ラムダ関数の使用が簡単になりました。これは、引数のタイプを自動的に推測できるようになったためです。つまり、このタイプを明示的に記述する代わりにautoをパラメータータイプとして使用できるようになりました。

connect(sender, &Sender::valueChanged, [=](const auto &newValue) { receiver->updateValue("senderValue", newValue); });
      
      





ラムダ関数は、演算子()演算子が実装されたファンクターです。 一般化されたラムダ関数では、この演算子はテンプレート関数として宣言されます。 このようなファンクターをサポートする変更を加え、これらの変更はQt 5.1に含まれました。 C ++ 14では、変数だけでなく式もキャプチャする機能が追加されています。

 connect(sender, &Sender::valueChanged, [receiver=getReceiver()](const auto &newValue) { receiver->updateValue("senderValue", newValue); });
      
      







定数式の要件の緩和



C ++ 11では、新しいconstexprキーワードが導入されました。 Qt 4.8では、新しいマクロQ_DECL_CONSTEXPRが導入されました。このマクロは、単語がコンパイラでサポートされている場合にconstexprに展開されます。 Qt 5では、このマクロは多数の機能に使用されますが、それは可能な場合のみです。

C ++ 14では、定数式の要件が緩和されました。 C ++ 11では、単一のreturnステートメントでのみconstexprを使用でき、const修飾子を持つメンバー関数でのみ使用できました。 C ++ 14では、コンパイル時にのみ計算が可能であれば、さらに多くのことができます。

 /*      ++11,      ,     .   ++14   */ constexpr int myFunction(int v) { int x = 1; while (x < v*v) x*=2; return x; }
      
      





C ++ 11でconstexprとして宣言されたクラスメンバー関数は自動的に定数として扱われます。つまり、クラスのフィールドは変更されません。 C ++ 14では、クラスの非定数メンバー関数もconstexprになります。 この変更の結果、constexprによって宣言されたクラスメンバー関数が、明示的なconst修飾子なしで、C ++ 14で非定数になりました。これは、バイナリファイルレベルでの非互換性を意味します。 幸いなことに、Qtでは、Q_DECL_CONSTEXPRマクロはすべてのクラスメンバー関数を定数であると明示的に宣言しているため、使用時にバイナリ互換性に違反することはありません。

そのため、たとえばoperator =など、コンパイル時に非定数クラス関数をコンパイルできます。 これを行うために、新しいマクロQ_DECL_RELAXED_CONSTEXPRがQt 5.5に導入され、コンパイラがC ++ 14モードの場合はconstexprにデプロイされます。



C ++ 14の小さな変更



C ++ 14標準では、開発をより便利にするために、いくつかの小さな変更が導入されています。 これらの変更はQtに直接影響しませんが、C ++ 14をサポートするコンパイラーを使用している場合、プログラムで使用できます。



番号区切り記号


コードで大きな定数を定義する必要がある場合は、アポストロフィを数字の区切りとして使用できます。

 int i = 123'456'789;
      
      







二項定数


C ++では、10進、8進(0から始まる)、および16進(0xから始まる)定数を定義できます。 0bプレフィックスを使用してバイナリ定数を定義できるようになりました。

 int i = 0b0001'0000'0001;
      
      







自動復帰型復帰


組み込み(インライン)関数がある場合は、戻り値のタイプとしてautoキーワードを使用できますが、明示的に指定することはできません。 コンパイラはそれを出力します:

 //      'int' auto sum(int a, int b) { return a+b; }
      
      





残念ながら、Qt mocは戻り値の型自体を判別できないため、Qtスロットまたはいわゆる呼び出し可能メソッドではサポートされていません。



テンプレート変数


以前は、テンプレート関数またはクラスを作成できました。 これで、テンプレートと変数のみを作成できます。

 template<typename T> const T pi = 3.141592653589793; /*...*/ float f = pi<float>; double d = pi<double>;
      
      







構造の初期化


C ++ 11では、ユーザー定義コンストラクターを持たない構造を初期化リスト(中括弧内のフィールド値)で初期化することが可能になりました。また、クラス定義で非静的クラスフィールドをデフォルト値に直接設定することも可能になりました。 しかし、C ++ 11では、これらの初期化オプションの両方を一度に使用することは不可能でした。 C ++ 14では、これが可能になりました。 このコードは期待どおりに機能します。

 struct MyStruct { int x; QString str; bool flag = false; QByteArray str2 = "something"; }; // ... //    C++11   MyStruct  POD MyStruct s = { 12, "1234", true }; Q_ASSERT(s.str2 == "something");
      
      







クラスメソッドの参照修飾子



これは実際にはC ++ 14ではなくC ++ 11でも導入されましたが、これらの修飾子はQt5でのみ使用を開始しました。以前の投稿では言及していませんでした。

次のコードを検討してください。

 QString lower = QString::fromUtf8(data).toLower();
      
      





ここで、fromUtf8は一時変数を返します。 toLowerメソッドがこの一時変数に割り当てられたメモリを使用し、その中で必要な変換を実行するとよいでしょう。 このような場合に特に、クラスメンバー関数のリンク修飾子が導入されました。

qstring.hからの簡略化されたコード:

 class QString { public: /* ... */ QString toLower() const & { /* ...         ... */ } QString toLower() && { /* ...      ... */ } /* ... */ };
      
      





toLowerメソッドの最後にある「&」と「&&」に注意してください。 これらはリンク修飾子であり、const修飾子が「this」の一貫性に応じてメソッドをオーバーロードできるように、「this」が指すタイプに応じて関数をオーバーロードできます。 toLowerが一時変数(rvalue)に対して呼び出された場合、2番目のメソッド(&&を使用)が選択され、コピーせずに行が変更されます。

Qt 5.4のこれらの修飾子で改善された関数:QString :: toUpper、QString :: toLower、QString :: toCaseFolded、QString :: toLatin1、QString :: toLocal8Bit、QString :: toUtf8、QByteArray :: toUpper、QByteArray: :toLower、QImage :: convertToFormat、QImage :: mirorred、QImage :: rgbSwapped、QVersionNumber ::正規化、QVersionNumber ::セグメント



標準ライブラリの変更



C ++ 11およびC ++ 14は、標準ライブラリに多くの構成を追加しました。これは、QtCoreの既存の構成とほぼ重複しています。 Qtはごくわずかな標準ライブラリを使用します。 通常、標準ライブラリがABIの一部になることは望ましくありません。 これにより、標準ライブラリ(libstdc ++やlibcppなど)が変更された場合でも、バイナリ互換性を維持できます。 Qtは、標準C ++ 11ライブラリを持たない古いプラットフォームもまだサポートしています。 これらの理由により、このライブラリの使用を制限しています。

ただし、例外があります-Qt5は非推奨のアルゴリズムを宣言しているため、STLアルゴリズムを使用することをお勧めします(たとえば、qSortの代わりにstd :: sort)。



おわりに



もちろん、プロジェクトで新しいC ++ 14コンストラクトを使用できるようになるまでには時間がかかる場合があります。 しかし、他の多くの人(Qt Creator、KDE、LLVM)と同様にそれらを適用し始めることを願っています。 新しいMSVCコンパイラでは、C ++ 14がデフォルトでアクティブになっています。clangとgccでは、特別なフラグを使用する必要があります(現時点では-std = c ++ 1yです)。 qmakeを使用すると、次のコマンドを使用して、Qt5.4以降でC ++ 14でビルドするようにプロジェクトを構成できます。CONFIG + = c ++ 14



All Articles