0

In the following C++ code (from a Microsoft COM header file), what is the part that starts with template<class Q>...?

I am thoroughly confused for other reasons as well, as although a struct is in use, it has class-like elements; for example, the public keyword.

extern "C++" {
    struct IUnknown {
    public:
        virtual HRESULT WINAPI QueryInterface(REFIID riid,void **ppvObject) = 0;
        virtual ULONG WINAPI AddRef(void) = 0;
        virtual ULONG WINAPI Release(void) = 0;
        template<class Q> HRESULT WINAPI QueryInterface(Q **pp) { return QueryInterface(__uuidof(*pp),(void **)pp); }
    };
  }
Sabuncu
  • 5,095
  • 5
  • 55
  • 89

1 Answers1

1

The part that starts with template<class Q> HRESULT WINAPI QueryInterface is a template member function. In other words, it's a function template that's a member of a class (or struct, in this case).

Being a template means you can pass any interface type as its parameter, and the compiler will generate a function to query an object for an interface of that type:

IFoo *x;
IBar *y;

if (foo.QueryInterface(&x) != S_OK) {
    // use x->whatever to invoke members of IFoo
}

if (foo.QueryInterface(&y) != S_OK) {
    // use y->whatever to invoke members of IBar
}

Since it's a function template, the compiler deduces the type for Q from the type of the parameter you pass so when you pass an IFoo **, Q has the type IFoo, and when you pass an IBar **, Q has the type IBar.

In C++, the only difference between a class and struct is that member visibility in a class defaults to private, but in a struct defaults to public (so the public: tag isn't accomplishing anything in this case).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Thank you soooo much. Silly question (if you'd humor me): In C++, can structs have methods as well? Reword: Obviously structs *can* have methods, but this is a complete surprise for me. What is the design reason behind this, possibly? – Sabuncu May 05 '15 at 14:10
  • @Sabuncu: Yes--as stated in the answer, in C++ a `struct` is *exactly* like a `class` except that visibility defaults to `public` instead of `private`. I believe the reasoning was probably pretty simple: to build on an existing concept instead of introducing something new and different for no particular reason. – Jerry Coffin May 05 '15 at 14:14
  • Also note that this is a COM interface which implies a rather rigid binary contract (the vtable is the relevant part here). The template method will not add anything to the vtable, so it does not break the contract. It has been added purely as a convenience in this header. The canonical version of IUnknown does not have this fourth method. – CÅdahl May 11 '15 at 05:53