내가 일하는 회사에서 'RestrictedMap'이라는 클래스를 만들었습니다. 이것은 표준 std :: map과 동일한 인터페이스를 제공하지만 [] 연산자는 사용할 수 없습니다. 일부 다른 기능이 클래스와 함께 편안하게 작동하도록 제공되었습니다. 내부적으로 클래스는 std :: map을 래핑합니다.std :: map 및 boost :: ptr_map 템플릿 및 상속에서 반환 값이 나 빠진다.
이제 RestrictedPointerMap이라고하는 boost :: ptr_map에 대해 동일한 작업을 수행하는 비슷한 클래스를 만들려고합니다. 이를 위해 RestrictedMapBase을 작성하여 랩핑해야하는 맵 유형을 템플릿 인수로 받아들이고 대부분의 구현을 포함합니다. 우리가 무엇을 사용했는지와 같은을 수행하고 새로운 표준 : :지도
- RestrictedMap을 : 두 클래스는 포장하는 그것의 파생지도의 유형을 지정 boost :: ptr_map을 래핑합니다.
코드는 다음과 같습니다. 클래스 완성을 위해 클래스를 단순화하지는 않았지만 나중에 관련 함수의 이름을 지정합니다.
이 나는 RestrictedPointerMap에 에게 getValue를 호출 할 경우를 제외하고, 대부분 작동
#pragma once
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/static_assert.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include <map>
/**
* Class that has the benefits of a map, but does not add an entry if it does not exists.
* Do not use RestrictedMapBase directly but use one of the derived classes (RestrictedMap or RestrictedPointerMap).
*/
template <typename MAP>
class RestrictedMapBase
{
public:
RestrictedMapBase(const MAP& map):
m_map(map)
{}
template<class InputIterator>
RestrictedMapBase(InputIterator first, InputIterator last):
m_map(first, last)
{}
RestrictedMapBase()
{}
/************************************************************************/
/* std::map interface */
/************************************************************************/
typedef typename MAP::iterator iterator;
typedef typename MAP::const_iterator const_iterator;
typedef typename MAP::value_type value_type;
typedef typename MAP::key_type key_type;
typedef typename MAP::mapped_type mapped_type;
typedef typename MAP::size_type size_type;
iterator begin() { return m_map.begin(); }
iterator end() { return m_map.end(); }
const_iterator begin() const { return m_map.begin(); }
const_iterator end() const { return m_map.end(); }
bool empty() const { return m_map.empty(); }
size_type size() const { return m_map.size(); }
iterator find(const key_type& key) { return m_map.find(key); }
const_iterator find(const key_type& key) const { return m_map.find(key); }
void clear() { m_map.clear(); }
void erase(iterator where) { m_map.erase(where); }
bool operator==(const typename RestrictedMapBase<MAP>& other) const { return m_map == other.m_map; }
bool operator!=(const typename RestrictedMapBase<MAP>& other) const { return m_map != other.m_map; }
bool operator<(const typename RestrictedMapBase<MAP>& other) const { return m_map < other.m_map; }
/************************************************************************/
/* extra */
/************************************************************************/
void erase(const key_type& key)
{
iterator iter(find(key));
assert(found(iter));
erase(iter);
}
void eraseIfExists(const key_type& key)
{
m_map.erase(key);
}
bool exists(const key_type& key) const
{
return found(find(key));
}
mapped_type& getValue(const key_type& key)
{
return const_cast<mapped_type&>(static_cast<const RestrictedMapBase<MAP>&> (*this).getValue(key));
}
const mapped_type& getValue(const key_type& key) const
{
const_iterator iter(find(key));
assert(found(iter));
return getData(iter);
}
mapped_type getValueIfExists(const key_type& key) const
{
BOOST_STATIC_ASSERT(boost::is_pointer<mapped_type>::value);
const_iterator iter(find(key));
if (found(iter)) {
return getData(iter);
} else {
return 0;
}
}
void setValue(const key_type& key, const mapped_type& value)
{
iterator iter(find(key));
assert(found(iter));
setData(iter, value);
}
void add(const key_type& key, const mapped_type& value)
{
assert(!exists(key));
insert(key, value);
}
void add(const RestrictedMapBase<MAP>& mapToAdd)
{
BOOST_FOREACH(value_type element, mapToAdd.m_map)
{
add(element.first, element.second);
}
}
void addOrReplace(const key_type& key, const mapped_type& value)
{
iterator iter(find(key));
if (found(iter)) {
setData(iter, value);
} else {
insert(key, value);
}
}
mapped_type* addDefaultConstructed(const key_type& key)
{
assert(!exists(key));
return &m_map[key];
}
private:
bool found(const const_iterator& iter) const
{
return iter != end();
}
const mapped_type& getData(const const_iterator& iter) const
{
return const_cast<const mapped_type&>(iter->second);
}
mapped_type& getData(const iterator& iter)
{
return const_cast<mapped_type&>(static_cast<const RestrictedMapBase<MAP>&>(*this).getData(iter));
}
void setData(const iterator& iter, const mapped_type& value)
{
getData(iter) = value;
}
virtual void insert(const key_type& key, const mapped_type& value) = 0;
protected:
MAP& getMap()
{
return m_map;
}
private:
MAP m_map;
};
template <typename KEYTYPE, typename DATATYPE>
class RestrictedMap: public RestrictedMapBase<std::map<KEYTYPE, DATATYPE> >
{
public:
RestrictedMap(const std::map<typename KEYTYPE, typename DATATYPE>& map): RestrictedMapBase(map)
{}
template<class InputIterator>
RestrictedMap(InputIterator first, InputIterator last): RestrictedMapBase(first, last)
{}
RestrictedMap()
{}
virtual void insert(const KEYTYPE& key, const DATATYPE& value)
{
getMap().insert(std::make_pair(key, value));
}
};
template <typename KEYTYPE, typename DATATYPE>
class RestrictedPointerMap: public RestrictedMapBase<boost::ptr_map<KEYTYPE, DATATYPE> >
{
public:
RestrictedPointerMap(const boost::ptr_map<typename KEYTYPE, typename DATATYPE>& map): RestrictedMapBase(map)
{}
template<class InputIterator>
RestrictedPointerMap(InputIterator first, InputIterator last): RestrictedMapBase(first, last)
{}
RestrictedPointerMap()
{}
virtual void insert(const KEYTYPE& key, DATATYPE* const& value)
{
/* boost::ptr_map::mapped_type does not equal the DATATYPE template parameter passed to it. Therefore this
* functions signature *looks* different from the RestrictedMapBase::insert signature */
getMap().insert(key, std::auto_ptr<DATATYPE>(value));
}
};
RestrictedMap.h. getData은 올바른 값을 반환하지만 이후에는 getValue 함수에서 잘못 처리됩니다. 잘못된 포인터를 반환합니다 (포인터가 잘못됨). 여기
문제 재생하는 코드이다TestClass.h을
#pragma once
class SomeClass
{
public:
SomeClass();
virtual ~SomeClass();
};
TestClass.cpp
#include "stdafx.h"
#include "TestClass.h"
#include <iostream>
SomeClass::SomeClass()
{
std::cout << "TestClass[" << this << "] created." << std::endl;
}
SomeClass::~SomeClass()
{
std::cout << "TestClass[" << this << "] deleted." << std::endl;
}
TestRestrictedPtrMap.cpp (주)
#include "stdafx.h"
#include "RestrictedMap.h"
#include "TestClass.h"
#include <boost/foreach.hpp>
int _tmain(int argc, _TCHAR* argv[])
{
typedef RestrictedPointerMap<int, SomeClass> MapType;
MapType theMap;
theMap.add(1, new SomeClass());
theMap.add(2, new SomeClass());
BOOST_FOREACH(MapType::value_type mapEntry, theMap) {
std::cout << mapEntry.first << " = " << mapEntry.second << std::endl;
}
SomeClass* oneClass = theMap.getValue(1);
std::cout << oneClass << std::endl;
SomeClass* twoClass = theMap.getValue(2);
std::cout << twoClass << std::endl;
std::cin.get();
return 0;
}
The o 이것의 utput은 다음과 같습니다 :
TestClass[0078A318] created.
TestClass[0078A448] created.
1 = 0078A318
2 = 0078A448
0018FBD4
0018FBD4
TestClass[0078A318] deleted.
TestClass[0078A448] deleted.
나는 그것이 잘못되는지 전혀 모른다. 내가 아는 한 반환 값은 마술에 의해 나 빠진다. 사전에 어떤 도움
감사합니다,
톰
RestrictedPointerMap
의 서명을 변경하는 것이 더 나은 할 수 RestrictedMapBase@DavidSchwartz : 'const'버전과 nonconst 버전 사이에서 작업을 복제하지 않는 것이 일반적인 전략입니다. 어느 쪽이라도 할 수는 있지만,'const' 버전이 아닌 오브젝트를 우연히 수정하지 않기 때문에'const' 버전 호출 (여기에 보여진 것처럼)이 더 좋습니다. 나는 Meyers의 Efficient C++에도 등장한다고 생각한다. –
이 코드는 Frenchto와 같습니다. 내 눈 : 녹슨 것 같습니다. 어쨌든, 목표를 위해 클래스 RestrictedMapBase : public MAP을 템플릿으로 만든 다음 [] 연산자를 어떻게 든 숨 깁니다. 아마도 사적으로 만들 수도 있습니다. –
kellogs