简体   繁体   English

C ++ Microsoft:如何将uuid / guid与模板特化相关联

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

I'd like to associate a uuid/guid with a template specialization. 我想将uuid / guid与模板专业化相关联。

The following code can be used to associate a uuid with a non-template interface (class, struct): 以下代码可用于将uuid与非模板接口(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. 无法将__declspec(uuid(...))添加到模板类定义中。 This is obvious, since different specializations of the interface need different uuids. 这是显而易见的,因为界面的不同特化需要不同的uuids。 So I tried to associate the uuid with a template specialization in the following way: 所以我尝试通过以下方式将uuid与模板特化相关联:

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"). 不幸的是,这也不起作用(__uuidof(。)失败,“没有GUID与此对象相关联”)。

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. 让我们进一步假设我想使用接口,因为我的应用程序使用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: 现在让我们进一步假设我有另一个模板对象,也实现了一个非常“复杂”的算法,它利用了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. 当CSquareAndAddOne :: SquandAndAddOne想要使用CTemplateImplementation专门化的__uuid时,问题就出现了。 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. 这不再起作用,因为没有与m_multiplier相关的GUID。 So how can I assign guids to the (three in this case) different implementations of CTemplateImplementation without duplicating code? 那么如何在没有重复代码的情况下为这些(在这种情况下为三个)CTemplateImplementation的不同实现分配guid? 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. 从CTemplateImplementation为不同类型派生不同的类是不可能的,因为CSquareAndAddOne中正确类型化的专业化的使用不能再用模板参数控制。

I tried some explicit instantiation magic and it works OK (at least with VS2008 SP1): 我尝试了一些明确的实例化魔法,它运行正常(至少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. 看起来最初的问题是__declspec试图在实际实例化之前将guid分配给类专门化。

Try: 尝试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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