4

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.

pnuts
  • 58,317
  • 11
  • 87
  • 139
Holger Strauss
  • 225
  • 2
  • 10
  • I'm not really sure because it's been a long time ago when working with this stuff, but I think ATL provides a solution for your problem. – πάντα ῥεῖ Aug 15 '12 at 09:40
  • Interfaces are typically not templates, instead they have definite types in them. Perhaps instead of applying GUID onto interface class, you could instead define an overloaded function `GUID Foo(ITemplateTest) { return ; }` which returns different identifiers for different types. – Roman R. Aug 15 '12 at 09:58
  • Thanks. Unfortunately, I have existing code based on __uuidof that I do not want to change (mainly because it is used with many other existing interfaces that do not have a defined overloaded 'guid'-return-function). So I'm still looking for some way to make __uuidof work. – Holger Strauss Aug 15 '12 at 10:04

2 Answers2

3

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.

Rost
  • 8,779
  • 28
  • 50
0

Try:

__interface __declspec(uuid("CF4AB938-8CE0-4AB7-A56C-0253B6018C26")) 
ITestFloat: ITemplateTest<float> {
    virtual void Test() = 0;
};
olivecoder
  • 2,858
  • 23
  • 22
  • This binds the uuid to ITestFloat, but not to ITemplateTest. – Holger Strauss Aug 15 '12 at 12:15
  • You can't bind anything to a template. The template is like a define that exist just when used , but you can instantiate from ITestFloat instead ITemplateTest – olivecoder Aug 15 '12 at 18:07
  • If is acceptable to bind na uuid to each template type so you can instantiate from ITestFloat instead ITemplateTest. – olivecoder Aug 15 '12 at 18:14
  • I understand that it doesn't make sense to bind the uuid to a template. But it would make sense to bind it to a template _specialization_. When you derive 'ITestFloat:ITemplateTest', you lose the advantage of template programming, because 'ITestDouble:ITemplateTest', 'ITestInt:ITemplateTest', ... would all require a separate implementation of the methods, while 'ITemplateTest' could be implemented with a single piece of code for all types. – Holger Strauss Aug 16 '12 at 07:34
  • You wrong. If your template has not other parameters then both solutions has the same effect. Anything you can do with a template specialization you also can do with a child class because the template parameter is already defined in both cases. – olivecoder Aug 16 '12 at 10:25
  • Better..,: using a class you can achive your purpose but not with a template – olivecoder Aug 16 '12 at 10:27
  • Thanks for taking your time. However, I think that your solution does not apply to my problem or I do not understand the solution correctly. I'll add a more complete example below the original question at the top, because the comment space is not sufficient here. – Holger Strauss Aug 16 '12 at 12:43