Prev: regarding Auto and decltype
Next: Template pointer and reference type parameters with tr1 variate_generator
From: jrwats on 26 May 2010 17:38 So we have this templated factory for COM objects. A simplistic view of it would be the following: template <class T> class Creator { public: // const& arguments template <class I> static HRESULT Create(I** ppI) { return Create(NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), ppI); } template <class TArg1, class I> static HRESULT Create(TArg1 t1, __deref_out I** ppI) { return Create(t1, NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), ppI); } // Handle Arguments 2 - 7 as above template <class TArg1, class TArg2, class TArg3, class TArg4, class TArg5, class TArg6, class TArg7, class TArg8, class I> static HRESULT Create(TArg1 t1, TArg2 t2, TArg3 t3, TArg4 t4, TArg5 t5, TArg6 t6, TArg7 t7, TArg8 t8, I** ppI) { HRESULT hr = S_OK; T* pT = NULL; // Creation code here... if (hr >= 0) { hr = __Init(pT, t1, t2, t3, t4, t5, t6, t7, t8); } else { return E_OUTOFMEMORY; } if (hr >= 0) { *ppI = pT; hr = S_OK; } return hr; } template <class TArg1, class TArg2, class TArg3, class TArg4, class TArg5, class TArg6, class TArg7, class TArg8> static HRESULT __Init(__in T* pT, TArg1 t1, TArg2 t2, TArg3 t3, TArg4 t4, TArg5 t5, TArg6 t6, TArg7 t7, TArg8 t8) { return pT->Initialize(t1, t2, t3, t4, t5, t6, t7, t8); } template <class TArg1, class TArg2, class TArg3, class TArg4, class TArg5, class TArg6, class TArg7> static HRESULT __Init(__in T* pT, TArg1 t1, TArg2 t2, TArg3 t3, TArg4 t4, TArg5 t5, TArg6 t6, TArg7 t7, NoArg) { return pT->Initialize(t1, t2, t3, t4, t5, t6, t7); } // handle Arguments 6 - 0 via template specialization as above }; The problem is passing in an instance of some class CFoo calls the copy constructor. And if I make all the arguments const& then people cannot do the following: HRESULT (*PfnCreator)(ISomeInterface* pSomeInterface, IDesiredObject** ppDesiredObject) = *ComCreator<CDesiredObject>::Create; Since the function signature is actually HRESULT Create(ISomeInterface* const& pSomeInterface, IDesiredObject** ppDesiredObject); So I'd like to avoid this as I'd hate for callers to have to go do this. I also can't defineCreate as follows template <class TArg1, class I> static HRESULT Create(TypeTraits<TArg1>::ParameterType t1, __deref_out I** ppI) { return Create(t1, NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), ppI); } As this simply can't work since template argument deduction has already happened to determine the type of TArg1. Are there any other solutions so this? Again I do *not* want an ubiquitous const&. Thanks! -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: McNepp on 27 May 2010 03:34
I faced a similiar problem when I wrote a template library to ease the use of the JNI. My solution was: Make the function's parameter types part of the class template, providing 'void' as default types for non-existing arguments. Then, partially specialize the class. With that scheme, you can apply type traits to the parameters! Here's a rough sketch, using a maximum of 2 parameters: // Primary template, will never be used with void for A1 or A2 template<class T,class A1=void,class A2=void> class Creator<T,A1,A2> { public: template<typename I> static HRESULT Create(I** ppI, TypeTraits<A1>::ParameterType a1, TypeTraits<A2>::ParameterType a2) { } }; template<class T> class Creator<T,void,void> { public: template<typename I> static HRESULT Create(I** ppI) { } }; template<class T,class A1> class Creator<T,A1,void> { public: template<typename I> static HRESULT Create(I** ppI, TypeTraits<A1>::ParameterType a1) { } }; On 27 Mai, 09:38, jrwats <jrw...(a)gmail.com> wrote: > So we have this templated factory for COM objects. A simplistic view > of it would be the following: > > template <class T> > class Creator > { > public: > // const& arguments > template <class I> > static HRESULT Create(I** ppI) > { > return Create(NoArg(), NoArg(), NoArg(), NoArg(), NoArg(), > NoArg(), NoArg(), NoArg(), ppI); > } > > template <class TArg1, class I> > static HRESULT Create(TArg1 t1, __deref_out I** ppI) > { > return Create(t1, NoArg(), NoArg(), NoArg(), NoArg(), > NoArg(), NoArg(), NoArg(), ppI); > } > > // Handle Arguments 2 - 7 as above > > template <class TArg1, class TArg2, class TArg3, class TArg4, > class TArg5, > class TArg6, class TArg7, class TArg8, class I> > static HRESULT Create(TArg1 t1, TArg2 t2, TArg3 t3, TArg4 t4, > TArg5 t5, > TArg6 t6, TArg7 t7, TArg8 t8, I** ppI) > { > HRESULT hr = S_OK; > T* pT = NULL; > > // Creation code here... > > if (hr >= 0) > { > hr = __Init(pT, t1, t2, t3, t4, t5, t6, t7, t8); > } > else > { > return E_OUTOFMEMORY; > } > > if (hr >= 0) > { > *ppI = pT; > hr = S_OK; > } > > return hr; > } > > template <class TArg1, class TArg2, class TArg3, class TArg4, > class TArg5, > class TArg6, class TArg7, class TArg8> > static HRESULT __Init(__in T* pT, TArg1 t1, TArg2 t2, TArg3 t3, > TArg4 t4, > TArg5 t5, TArg6 t6, TArg7 t7, TArg8 t8) > { > return pT->Initialize(t1, t2, t3, t4, t5, t6, t7, t8); > } > > template <class TArg1, class TArg2, class TArg3, class TArg4, > class TArg5, > class TArg6, class TArg7> > static HRESULT __Init(__in T* pT, TArg1 t1, TArg2 t2, TArg3 t3, > TArg4 t4, > TArg5 t5, TArg6 t6, TArg7 t7, NoArg) > { > return pT->Initialize(t1, t2, t3, t4, t5, t6, t7); > } > > // handle Arguments 6 - 0 via template specialization as above > > }; > > The problem is passing in an instance of some class CFoo calls the > copy constructor. And if I make all the arguments const& then people > cannot do the following: > > HRESULT (*PfnCreator)(ISomeInterface* pSomeInterface, IDesiredObject** > ppDesiredObject) = > *ComCreator<CDesiredObject>::Create; > > Since the function signature is actually > HRESULT Create(ISomeInterface* const& pSomeInterface, IDesiredObject** > ppDesiredObject); > > So I'd like to avoid this as I'd hate for callers to have to go do > this. > > I also can't defineCreate as follows > > template <class TArg1, class I> > static HRESULT Create(TypeTraits<TArg1>::ParameterType t1, > __deref_out I** ppI) > { > return Create(t1, NoArg(), NoArg(), NoArg(), NoArg(), > NoArg(), NoArg(), NoArg(), ppI); > } > > As this simply can't work since template argument deduction has > already happened to determine the type of TArg1. > > Are there any other solutions so this? Again I do *not* want an > ubiquitous const&. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |