A template that provides an interface

Is it possible to create a template that takes types that implement a specific interface? For example, I want to tell the user of the template: you can store anything in my container if it implements the Init () and Destroy () methods.

thank

+2


source to share


7 replies


A limited subset of (intended but unfortunately abridged) functionality of C ++ 0x concepts is provided by the Boost concept checking library . You can use it by creating a proof-of-concept class for your required interface.



+6


source


First, if you need Init and Destroy, that means the template code is using them somewhere. This means that their existence has already been verified by the compiler, since the template will not compile if the type does not have these methods.

However, if you want to check them, then one way would be to use their addresses in some compilation context, for example

template <class T>
class X
{
private:
    template <unsigned N>
    struct Number {};
    Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy();
};

struct A
{
    bool Init();
    void Destroy();
};

struct B {};

int main()
{
    X<A>();
    X<B>();
}

      

With Comeau, the conclusion is:



"ComeauTest.c", line 7: error: class "B" has no member "Init"
          Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy();
                            ^
          detected during instantiation of class "X<T> [with T=B]" at line 21

"ComeauTest.c", line 7: error: class "B" has no member "Destroy"
          Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy();
                                               ^
          detected during instantiation of class "X<T> [with T=B]" at line 21

      

However, this breaks if any of the required methods are overloaded, and naturally this still doesn't check if those methods have a suitable prototype.

For example, you might be expecting bool Init (int, int). You can use static_cast to verify the exact signature, but again this can introduce unnecessary type constraints. For example, so what if some class has Init (long, long) instead of bool?

Either way, this effort seems necessary only to make the error messages more obvious. However, I highly doubt that any message you would otherwise receive without any concept checks (a la "there is no suitable Init method to call with T = X when used here") is bad.

+2


source


No, It is Immpossible.

Patterns are replaced by one type, not many different ones.

Consider creating a base class that all possible members must inherit and leave all templates.

Basically you are introducing existential types , which is not supported in C ++.

+1


source


Not possible in the current standard. I believe this is possible through "concepts" that supposedly (?) Become standard in C ++ 0x.

0


source


Well, I guess you could define a method that calls Init()

and Destroy()

argument template, and somehow call this method in debug mode.

Alternatively, you can define an interface and apply that interface in your implementation. This can also be disabled in release mode.

0


source


Yes, you can.

It is, however, quite complicated (advanced template metaprogramming) The whole concept is built around the "Failure Replacement Is Not an Error (SFINAE)" in C ++ templates.

In essence, you can use a template, for example, 'template <typename T, void (T::*)()>'

and instantiate using <T, T::Init>

in your vector. If the substitution doesn't exist, you'll get a substitution error (the SFINAE principle is used here because most of the time you would like to use the constructor instead).

This is, of course, a more simplified description. I wish I could provide a better one right now, but you can take a look at this discussion . search for has_member and is_call_possible.

Hope this helps. Oren

0


source


Actually, it's the other way around: if your template requires Init()

and Destroy()

, it can't be created with any type that doesn't have those two.

The only problem with templates in this regard is that the requirement is implicit (i.e. the template will not compile at the point that the template requires) and not explicitly (i.e. the compiler tells you it is missing at the instance point ). The concepts were supposed to fix this, but they were taken from the next standard some time ago.

0


source







All Articles