2

std::map をラップし、キーが承認された有効な文字列の 1 つであることを確認し、承認されたすべての有効な文字列のデフォルト値を持つようにマップを初期化するクラスを作成しようとしています。添え字演算子、特にその const バージョンを機能させる際に問題が発生しています。

これが私のクラスのプロトタイピングコードです:

#include <set>
#include <string>
#include <map>

class foo {
  public:
    foo() {}
    const double & operator[](const std::string key) const {
      return data[key];
    }
  private:
    static const std::set<std::string> validkeys;
    std::map<std::string, double> data;
};

const std::set<std::string> foo::validkeys = {"foo1", "foo2"};

これをコンパイルすると (-std=c++0x で g++ を使用)、次のコンパイル エラーが発生します。

|| /home/luke/tmp/testmap.cc: In member function 'double& foo::operator[](std::string) const':
testmap.cc|10 col 22 error| passing 'const std::map<std::basic_string<char>, double>' as
'this' argument of 'mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const
key_type&) [with _Key = std::basic_string<char>, _Tp = double, _Compare =
std::less<std::basic_string<char> >, _Alloc = std::allocator<std::pair<const 
std::basic_string<char>, double> >, mapped_type = double, key_type = 
std::basic_string<char>]' discards qualifiers

私が何をしてもこれを修正するようには見えません。私が試してみました

  • validkeys を std::set および data std::map にする
  • 文字列の代わりに const char * を使用する
  • const double の代わりに const double または double を返す &
  • set の代わりに list と vector を使用して有効なキーを格納する

この問題に正しく取り組んでいるかどうかさえわからないので、この種の機能を可能にするクラスを作成する他の簡単な方法がある場合:

foo a;
a["foo2"] = a["foo1"] = 5.0;
// This would raise a std::runtime_error because I would be checking that
// "foo3" isn't in validkeys
a["foo3"] = 4.0;

どんな提案でも大歓迎です。

解決

以下はまさに私が望むように機能します。有効なキーのセットにないキーを設定または取得しようとすると、基本的な例外さえあります。

#include <iostream>
#include <string>
#include <map>
#include <set>
#include <stdexcept>

class myfooexception : public std::runtime_error
{
  public:
    myfooexception(const std::string & s)
      : std::runtime_error(s + " is not a valid key.") {}
};

class foo {
  public:
    foo() {
     for (std::set<std::string>::iterator it = validkeys.begin();
          it != validkeys.end();
          ++it) {
       data[*it] = 0.0;
     }
    }
    const double & operator[](const std::string & key) const {
      if (data.find(key) == data.end()) {
        throw myfooexception(key);
      } else {
        return data.find(key)->second;
      }
    }
    double & operator[](const std::string & key) {
      if (data.find(key) == data.end()) {
        throw myfooexception(key);
      } else {
        return data[key];
      }
    }
  private:
    static const std::set<std::string> validkeys;
    std::map<std::string, double> data;
};

const std::set<std::string> foo::validkeys = {"foo1", "foo2"};

int main(void)
{
  foo a;
  a["foo1"] = 2.0;
  a["foo1"] = a["foo2"] = 1.5;
  // a["foo3"] = 2.3; // raises exception:  foo3 is is not a valid key
  const foo b;
  std::cout << b["foo1"]; // should be ok
  // b["foo1"] = 5.0;  // compliation error, as expected: b is const.

  return 0;
}
4

4 に答える 4

3

operator []は で宣言されていませんconst。これは、キーが見つからない場合に も新しい要素を挿入し、マップされた値への参照を返すためですstd::map。にしたい場合は、代わりにメソッドoperator []を使用できます。map::findmap::operator[]operator[]const

于 2012-02-20T07:15:52.923 に答える
2

添字演算子 forstd::mapは、まだ存在しない場合に新しい要素を挿入するため、非 const です。マップに const を持たせたい場合は、operator[]を使用map::find()してテストしmap::end()、エラー ケースを処理するものを作成する必要があります。

于 2012-02-20T07:13:51.260 に答える
1

const オブジェクトを変更しようとしています!! set.const メンバーの const を削除してください。一度初期化すると変更できません。

于 2012-02-20T07:12:06.253 に答える
0

に割り当てようとしてstd::mapいますが、関数が宣言されconstており、 も返されconstます。両方を削除するconstと、機能するはずです。

于 2012-02-20T07:09:18.520 に答える