template <class> class automation_vector;
class automation_vector_base
{
friend void trace(CComVariant &v);
typedef automation_vector_base self;
protected:
...
void attach(VARIANT &v) throw();
void detach(VARIANT &v) throw();
public:
...
static void com_enforce(HRESULT hr) throw(std::runtime_error);
// The size of the vector
size_t size() const throw()
{
_ASSERT(valid());
return m_Value.vt == VT_EMPTY ? 0 : bounds().cElements;
}
size_t capacity() const throw()
{
return size();
}
// checks whether the vector is empty
bool empty() const throw()
{
return size() == 0;
}
~automation_vector_base() throw();
// Creation mode
enum TCreateMode { MOVE, COPY };
protected:
// Constructors/destructors are protected to prevent
// direct instantiation
self(unsigned Elements, VARENUM VarType)
throw(std::invalid_argument, std::runtime_error);
...
void resize(size_type NewSize, VARENUM Type);
void clear()
{
_ASSERT(!V_ISBYREF(&m_Value));
_ASSERT(empty() || array().cLocks == 0);
com_enforce(m_Value.Clear());
}
...
private:
...
// The actual holder of the array
CComVariant m_Value;
};
inline void from_automation(SAFEARRAY &, void *)
{
}
inline void to_automation(SAFEARRAY &, void *)
{
}
template <class T>
void
from_automation(SAFEARRAY &Array, automation_vector<T> *pDummy);
template <class T>
void
to_automation(SAFEARRAY &Array, automation_vector<T> *pDummy);
template <class T> class automation_vector :
public automation_vector_base
{
typedef automation_vector_base base;
typedef automation_vector self;
...
public:
...
// *** Static VARIANT type mapped from the C++ type
static VARENUM myVARENUM()
{
// If you have an error on the line below,
// you've instantiated automation_vector with the
// wrong type
static_checker<sizeof(T) == sizeof(
Configure::deduceVARENUM(T()).size_checker)>();
return static_cast<VARENUM>
(Configure::deduceVARENUM(T()).vt);
}
automation_vector(VARIANT &vSource, TCreateMode Mode)
throw(std::invalid_argument, std::runtime_error)
: base(0, myVARENUM())
{
if (Mode == COPY)
{
// Make a copy and attach to it
CComVariant v(vSource);
attach(v);
}
else
// Attach directly to the source
attach(vSource);
}
...
void attach(VARIANT &vSource)
throw(std::invalid_argument, std::runtime_error);
void detach(VARIANT &Var)
{
_ASSERT(_CrtIsValidPointer(&Var, sizeof(VARIANT), true));
com_enforce(::VariantClear(&Var));
unlock();
base::detach(Var);
}
CComVariant detach()
{
CComVariant v;
detach(v);
return v;
}
...
protected:
void lock();
void unlock();
};