C++ Microsoft: How to associate uuid/guid with template specialization
c++, com, templates
Solution
I tried some explicit instantiation magic and it works OK (at least with VS2008 SP1):
template<class T> __interface ITemplateTest { void Test(T t); }; // Interface declaration
template __interface ITemplateTest<float>; // Explicit instantiation
template __interface __declspec(uuid("CF4AB938-8CE0-4AB7-A56C-0253B6018C26") ITemplateTest<float>; // Repeat explicit instantiation with uuid association
GUID guid = __uuidof(ITemplateTest<float>); // Enjoy! :-)
Looks like initial problem was that `__declspec` tried to assign guid to class specialization before it was actually instantiated.
Problem
I'd like to associate a uuid/guid with a template specialization. The following code can be used to associate a uuid with a non-template interface (class, struct): ``` __interface __declspec(uuid("CECA446F-2BE6-4AAC-A117-E395F27DF1F8")) ITest { virtual void Test() = 0; }; GUID guid = __uuidof(ITest); // OK ``` Now I have a templated interface ``` template<class T> __interface ITemplateTest { virtual void Test(T t) = 0; }; ``` and I'd like to make the following work: ``` GUID templateGuid = __uuidof(ITemplateTest<float>); ``` It is not possible to add the __declspec(uuid(...)) to the template class definition. This is obvious, since different specializations of the interface need different uuids. So I tried to associate the uuid with a template specialization in the following way: ``` template<> __interface __declspec(uuid("CF4AB938-8CE0-4AB7-A56C-0253B6018C26")) ITemplateTest<float>; ``` Unfortunately, this doesn't work either (__uuidof(.) fails with "no GUID has been associated with this object"). Is there any solution to my problem? Here is a more complete example added later after some answers: Let's say I have a complex algorithm that works on different data types. This "complex" algorithm is squaring a number for the sake of simplicity. I'd like to implement my algorithm only once, so templates is the way to go. Let's further assume that I want to use interfaces, because my app makes use of COM. So here is an interface and a templated object that implements this interface: ``` template<class T> __interface ITemplateTest { virtual T Square(T t) = 0; }; template<class T> class CTemplateImplementation : public ITemplateTest<T> { public: virtual T Square(T t) { return t * t; }; }; ``` This allows to do something like ``` CTemplateImplementation<double> xDouble; CTemplateImplementation<float> xFloat; CTemplateImplementation<int> xInt; std::cout << xDouble.Square(5.) << std::endl << xFloat.Square(5.0f) << std::endl << xInt.Square(5) << std::endl; ``` Now let's further assume that I have another template object, also implementing a very "complex" algorithm, that makes use of CTemplateImplementation: ``` template<class T> class CSquareAndAddOne { private: CTemplateImplementation<T> m_squarer; public: T SquareAndAddOne(T t) { return m_squarer.Square(t) + T(1); } }; ``` This object can now be used in the same way: ``` CSquareAndAddOne<double> yDouble; CSquareAndAddOne<float> yFloat; CSquareAndAddOne<int> yInt; std::cout << yDouble.SquareAndAddOne(5.) << std::endl << yFloat.SquareAndAddOne(5.0f) << std::endl << yInt.SquareAndAddOne(5) << std::endl; ``` The problem arises, when CSquareAndAddOne::SquandAndAddOne wants to make use of the __uuid of a CTemplateImplementation specialization. Try the following: ``` T SquareAndAddOne(T t) { GUID guid = __uuidof(m_multiplier); return m_squarer.Square(t) + T(1); } ``` This doesn't work any more, because there is no GUID assiciated with m_multiplier. So how can I assign guids to the (three in this case) different implementations of CTemplateImplementation without duplicating code? Can you provide a complete solution? Deriving different classes from CTemplateImplementation for different types is not possible, since usage of the correctly typed specialization in CSquareAndAddOne can not be controlled with a template argument any more.