2017-07-26 8 views
3

std::mapdocumentationによれば、キーと値のペアはstd::pair<const Key, Value>に格納されているため、マップのキーはconstです。なぜstd :: mapのキーをnon-constを期待する関数に渡すことができますか?

ここで私はstd::mapを持っていると想像してください。ここで、キーはいくつかのオブジェクトへのポインタです。

struct S {}; 
struct Data {}; 
using MyMap = std::map<S*, Data>; 

のもS*パラメータを受け付ける関数fooがあると仮定しましょう。

void foo(S* ptr) { /* modify the object (*ptr) */ } 

さて、質問です:私はとMyMapを反復処理するときに、範囲ベースのforループ、私はfooにマップ要素のキーを渡すことができる午前:

MyMap m = getMyMapSomehow(); 
for (auto elem : m) 
{ 
    static_assert(std::is_const<decltype(elem.first)>::value, "Supposed to be `const S*`"); 
    foo(elem.first); // why does it compile? 
} 

だから、でも私をかかわらず、 static_assertが成功します(したがって、elem.firstのタイプがconst S*であると仮定します)、fooへの呼び出しはうまくコンパイルされます。したがって、ポインタからconstへの背後にあるオブジェクトを変更できるかのように見えます。

なぜ私はそれを行うことができますか?

P.S.ここに私の要点を示すlive example at Coliruがあります。簡潔にするため、SDataの代わりにintを使用します。ここで

+0

要素のコピーを作成しています。あなたはその個人的なコピーであなたが望むものを何でもすることができます... –

+2

constへのポインタと不変なポインタを混同しないでください! –

+0

@KerrekSBああ、確かに!私の脳は私の仕事日の終わりに私を混乱させる:)ありがとう! –

答えて

5

ので、私はelem.firstのタイプはmapに格納されている鍵const S*

番号であることを前提としていconstであり、これはstd::map<S*, Data>を意味し、キーは(constポインタ)であり、(すなわち、const)。したがって、foo(S* ptr)に渡すと問題ありません。constポインタ自体がパラメータにコピーされます。

+0

あなたは正しいです、 'const T *'と 'T * const'を混合しました。そのようなことは、仕事の終わりに時々起こる:-)ありがとう! –

+0

@VasiliyGalkin:1つのメモ: 'const X *'と 'X const *'は同じものですが、 'X const *'と書くのは特に視覚的に考えるとテンプレートやtypedefを扱うときに便利です。 – Nawaz

+0

@Nawazナー、私はそれに同意します'。しかし、私はしないでしょう'もう一つの 'const T *' vs 'T const *' holywarのどちらかを始めたいと思っています) –

3

は、あなたがそれをうまくできるかどうか、単純な例です。

void f(int);   // takes a non-const int 

int main() { 
    std::set<int> s; // elements are const ints 
    for (auto n : s) { 
     f(n);   // OK!? 
    } 
} 
+0

ああ、確かに!私はキータイプが 'const T *'ではなく 'T * const'であるという事実に十分注意を払っていませんでした。ありがとう! –

+0

'auto n'はコピーを作成し、' f(int) 'はコピーをとります。だから、私はこの答えが何をコピーを使って説明しようとしているのか理解できませんでした! – Nawaz

+0

@Nawaz:これは基本的にOP面と同じ状況です:非const値をとる関数は、const set要素の(copy of)定数で呼び出すことができます。 'f(int&)'と 'for(auto&n:s)'があればコードは機能しないことに注意してください。私は第2レベルの混乱があると理解していますが、単純な例の周りを頭で囲むことができれば、元の状況について正しい質問をするのに十分な差分情報があります。 –

1

std::map<K, V>::value_typeは、前述のとおりstd::pair<const K, V>です。したがってconst KKの代わりにS*と表示されますか?あなたを驚かせるかもしれない答えは、const S*ではありません。むしろS* constです。

関連する問題