我想用这样的签名创建一个函数:
// 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);
除了使用模板为lookup()
提供两个定义,一个用const
参数2和3显示,另一个用非const参数2和3,在C ++中有更好的方法完成此操作更类似于const int &
如何在上面的示例中传递非const int
。换句话说,我可以只有一个功能而不是两个吗?
答案 0 :(得分: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
可以同时为map
和const map
,因此T&
为map&
或const map&
。
答案 1 :(得分: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!
}