简体   繁体   中英

C++ Microsoft: How to associate uuid/guid with template specialization

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.

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.

Try:

__interface __declspec(uuid("CF4AB938-8CE0-4AB7-A56C-0253B6018C26")) 
ITestFloat: ITemplateTest<float> {
    virtual void Test() = 0;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM