나는 비슷한 방법을 찾아내는 기술을 찾고 있습니다. 문제는 다음과 같습니다. 검색을 수행하려면 컨테이너 내용을 수정할 필요가없는 컨테이너에서 find 메서드가 필요합니다. 그러나 이후에 const 및 비 const 버전이 있어야하며, const_iterator 대신 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를 작성하고 내 공연을 망칠 수있는 것처럼 보일 것 같습니다.
는마누엘에게 미리, 환호에
개인적인 것은 없지만 Q를보고 포기하면 코드가 너무 많이 손상됩니다. : –
'std :: find'의 잘못된 점은 const가 아닌 반복자를 받아들이고 반환합니다. –
std :: find는 반복적으로 (선형 복잡도) 많은 경우에, 특히 위에서 밑줄이 쳐진지도 케이스에서, 그러한 경우에는 자신 만의 구현이 필요하고 좋은 디자인이 필요한 그런 일을하는 것입니다. 물론 문제는 함수를 찾는 것이 아니라 컨테이너를 수정하지만 반복자를 반환하는 함수에 국한됩니다 const 객체와 iterator를 다룰 때 const_iterators를 돌려 주길 원할 것입니다. –