4

次のようなシグネチャを持つ関数を作成したいと思います。

// Set found to be an iterator to the location of key in map or end()
// if not found.
bool lookup(const Key &key,
            const std::map<Key, Value> &map,
            std::map<Key, Value>::const_iterator &found);

しかし、見つかった値を変更できるように、マップとイテレータが const でない場合にも呼び出したいと思います。

const Key key;
std::map<Key, Value> map;
std::map<Key, Value>::iterator found;

if (lookup(key, map, found)) {
  found->second.modifingNonConstFunction()
}

std::map<Key, Value>::iteratorしかし、オブジェクトを関数に渡すことができるとは思えません。オブジェクトstd::map<Key, Value>::const_iteratorは型が異なるためです。一方、通常は、constこのような型の C++ 宣言の一部であり、非 const 型をに昇格させることができます。 const 型:

void someFunction(const int &arg);

int notConstArg = 0;
someFunction(nonConstArg);

テンプレートを使用して の 2 つの定義を提供する以外にlookup()、1 つは引数 2 と 3 で示され、もう 1constつは非 const 引数 2 と 3 で示されていますが、C++ でこれを達成するためのより良い方法はconst int &、非 を渡す方法に似ています。int上記の例ではconstです。つまり、関数を 2 つではなく 1 つにすることはできますか?

4

2 に答える 2

4

関数が単純な場合、またはバイナリの肥大化を気にしない場合は、すべてのパラメーターをテンプレート パラメーターにします。

template <typename Key, typename T, typename Iter>
bool lookup(Key const& key,
            T& map,
            Iter &found)
{
  return (found=map.find(key))!=map.end();
}

int main()
{
  std::map<std::string, int> m; m["hello"] = 42;
  std::map<std::string, int> const cm(m.begin(), m.end());

  std::map<std::string, int>::iterator it;
  std::map<std::string, int>::const_iterator cit;

  std::cout << std::boolalpha << lookup("hello", m, it) << '\n'; // Key isn't even std::string
  std::cout << std::boolalpha << lookup("hello", m, cit) << '\n';
  //std::cout << std::boolalpha << lookup("hello", cm, it) << '\n'; // error
  std::cout << std::boolalpha << lookup("hello", cm, cit) << '\n';
}

これは両方にTなる可能性があるため機能し、 orも同様です。mapconst mapT&map&const map&

于 2013-01-28T21:25:11.177 に答える
3

いいえ、オーバーロード/テンプレート マジックなしでこれを行うことはできないと思います。

コンパイラは、次のシナリオからユーザーを保護しています。

typedef vector<int> T;

const T v;  // Can't touch me

void foo(T::const_iterator &it) {
    it = v.begin();  // v.begin() really is a const_iterator
}

int main() {
    T::iterator it;
    foo(it);
    *it = 5;   // Uh-oh, you touched me!
}
于 2013-01-28T21:16:22.783 に答える