我正在寻找一种技术来寻找类似的方法。问题如下。我需要一个容器上的 find 方法,该方法不需要修改容器内容来进行搜索。但是,它应该有一个 const 和一个非常量版本,因为在返回迭代器而不是 const_iterator 的情况下,它可能导致容器的修改。在这两种情况下,代码将完全相同,只有访问器将被评估为 constXXX 或 XXX 并且编译器将完成这项工作。从设计和维护的角度来看,将这两种方法实现两次并不明智。(而且我真的很想避免为此使用宏......)我的意思也很好地说明了 stl_tree.h 中 stl 的 gcc 实现中的那段代码:
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
typename _Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::iterator
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
find(const _Key& __k)
{
iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
return (__j == end()
|| _M_impl._M_key_compare(__k,
_S_key(__j._M_node))) ? end() : __j;
}
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
typename _Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::const_iterator
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
find(const _Key& __k) const
{
const_iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
return (__j == end()
|| _M_impl._M_key_compare(__k,
_S_key(__j._M_node))) ? end() : __j;
}
您可以看到方法的原型不同,但实现中编写的代码实际上是相同的。
我想出了两种可能的解决方案:第一种是使用 const_cast,另一种是使用辅助模板结构。我在这里制作了这两种方法的一个简单示例:
#include <iostream>
using namespace std;
struct Data
{
typedef int* iterator;
typedef const int* const_iterator;
int m;
Data():m(-3){}
};
struct A : public Data
{
const_iterator find(/*const Key& k */) const
{
A *me = const_cast < A* > ( this );
return const_iterator( me->find(/*k*/) );
}
iterator find(/*const Key& k */){
return &m; }
};
//the second one is with the use of an internal template structure:
struct B : public Data
{
template<class Tobj, class Titerator>
struct Internal
{
Titerator find( Tobj& obj/*, const Key& k */ ){
return &(obj.m); }
};
const_iterator find( /*const Key& k */ ) const
{
Internal<const B, const_iterator> internal;
return internal.find( *this/*, k*/ );
}
iterator find( /*const Key& k */ )
{
Internal<B,iterator> internal;
return internal.find( *this/*, obs*/ );
}
};
int main()
{
{
A a;
a.find();
A::iterator it = a.find();
cout << *it << endl;
const A& a1(a);
A::const_iterator cit = a1.find();
cout << *cit << endl;
}
{
B b;
b.find();
B::iterator it = b.find();
cout << *it << endl;
const B& b1(b);
B::const_iterator cit = b1.find();
cout << *cit << endl;
}
}
这可能是一个众所周知的问题,我想知道是否有一些 c++ 大师想出了一个好的设计模式来解决这个问题。特别是我想知道是否有人认为这两种方法中的一种存在问题(特别是在性能方面)。由于第一个更容易理解,我更喜欢它,尤其是在阅读了以下内容之后: Constants and compiler optimization in C++ 这似乎让我不必担心编写 const_cast 并破坏我的表现。
提前谢谢你,干杯,
曼努埃尔