Reputation: 285
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.
Upvotes: 4
Views: 3967
Reputation: 9089
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.
Upvotes: 3
Reputation: 2914
Try:
__interface __declspec(uuid("CF4AB938-8CE0-4AB7-A56C-0253B6018C26"))
ITestFloat: ITemplateTest<float> {
virtual void Test() = 0;
};
Upvotes: 0