const
型修飾子は、C++ 言語設計の宝石の 1 つです。この機能を取り囲むように、"const
const
を防止するための「正しさ」の練習 オブジェクトが変異するのを防ぎます。 const
ほとんどのクラスの実装では、正確性のルールに従うのは簡単ですが、型消去のあるクラスについては注意が必要です。残念ながら、標準ライブラリ タイプ std::function
型消去によって実装されます。そして、近視のために、const-correctness ルールに従わない行儀の悪い市民の 1 つになります。
問題
std::function
1 つの const メンバー operator()
があります 、それでも基になる関数を変更できます。たとえば、
const std::function<int()> f {[x=0]() mutable { return ++x; }};
f(); // returns 1
f(); // returns 2
ドキュメント N43481 この懸念を最初に公式化した。
修正
function
の実装 のようなクラスには、const
用に個別の特殊化が必要です。 const
以外 .
template<class Sig> class function; // not defined
template<class R, class... Args>
class function<R(Args...)>;
template<class R, class... Args>
class function<R(Args...) const>;
operator()
const
の 特殊化には const
の注釈を付ける必要があります 、しかし const
のコンストラクター 特殊化は変更可能な関数オブジェクトを受け入れません.
function<int() const> f1 {[x=0]() { return x; }};
f1() // ok;
function<int() const> f2 {[x=0]() mutable { return ++x; }}; // Does not compile
一方、operator()
非 const
の 特殊化には const
がありません 型署名であるため、const
を呼び出すことはできません そのような関数のバージョン:
function<int()> f1 {[x=0]() mutable { return ++x; }};
f1(); // ok
const function<int()> f2 {[x=0]() mutable { return ++x; }};
f2(); // Does not compile
未来
std::function
とは思わない 下位互換性を損なうような変更を加えることはできません。この記事の執筆時点 (2019 年 12 月) で、私の賭けは提案された std::unique_function
にあります。 2
、これは std::function
のドロップイン置換です これにより、他の機能の中でも const-correctness バグが修正されます。標準で代替案ができたら std::function
std::auto_ptr
のように非推奨にすることができます .それまでの間、いつでも unique_function
を実装できます Github でそれを実装するための小さなライブラリがあります。