警告したいだけです。C++ 14は
constexpr関数の1つの側面でC ++ 11と後方互換性がありません。
C ++ 11では、
constexprメンバー関数を定義すると、暗黙的に
const指定子が取得されます。
get関数の最初の宣言は、明示的に指定しなくても
const指定子を受け取ります。 したがって、これら2つの関数は、
constバージョンと非
constバージョンです。
C ++ 14では、これは当てはまりません。両方の宣言が、異なる戻り値を持つメンバー関数の同じ非
constバージョンを決定するため、コンパイルエラーが発生します。
constexpr関数の使用を既に開始していて、暗黙的な
const指定子を希望している場合は、C ++ 14コンパイラーに切り替えることを決定した場合にコードがコンパイルし続けるように、明示的に追加することをお勧めします。
暗黙のconst何が問題になっていますか?
次のようにタイプを使用しようとすると、問題が始まります。
(やや珍しい)C ++ルールによれば、一時オブジェクトのメンバー関数を選択するときは、
constバージョンよりも
constバージョンの方が適しています。 非
constメンバー関数
get constexprで
getないため、
constexpr変数の初期化には使用できず、コンパイル段階でエラーが発生します。 この関数を
constexprにすることはできません
constexprが自動的に追加されるためです...
最適な関数を選択するためのルールは、一時オブジェクトに最適な非メンバー関数を選択する方法に少し反するため、珍しいと言いました。 この場合、非
constバージョンへのリンクの
const左辺値を優先します。
何が起こるか見てください:グローバル変数
N定数で
Nません。 したがって、2番目の非
constオーバーロード関数は、ポインター
P初期化時に呼び出されるように選択されます
P しかし、非
const関数には
constexprがまだあり
constexpr ! そして、すべてのルール「
constexprは
const意味する」は、非静的メンバー関数の暗黙の
this引数にのみ適用されるためです。
constexpr関数は、非
constオブジェクトへの参照を取得し、非
constサブオブジェクトへのリンクを返すことができます。 ここには問題はありません。グローバルオブジェクトのアドレスは一定であり、コンパイル時に既知です。 ただし、アドレス
Pの値は一定で
Pなく、後で変更できます。
前の例がやや難解に見える場合は、次のより現実的な例を検討してください。
ここではすべて正常に機能しますが、
addressをメンバー関数にしようとすると、機能しなくなります。
これは、
maddress const指定
maddress暗黙的に定義され、
thisが
NonNegative const*型であり、
NonNegative*変換できないためです。
これはメンバー関数自体が
constであるのではなく、関数
に対する暗黙の (
this )引数であることに注意してください。 メンバー関数宣言は、次のように擬似コードで書き直すことができます。
そして、この暗黙的な関数引数は、他の関数引数とは異なり、(時には望ましくない)
const修飾子を取得します。
この非対称性はC ++ 14で削除されます。 暗黙的な引数(
this )の
const指定子が必要な場合は、自分で追加する必要があります。 次のコードは、C ++ 14で有効です。