template which enforces interface
Is it possible to create a template accepting types which implement certain interface?
For example, I want to say to template user: you can store anything in my container as long as it开发者_开发百科 implements Init()
and Destroy()
methods.
Thanks
A limited subset of the (intended, but unfortunately cut) C++0x functionality of concepts is provided by the Boost Concept Check library. You can harness it by creating a concept check class for your required interface.
Firstly, if you require the existence of Init and Destroy, it means the template code uses them somewhere. This means, their existance is already checked by the compiler, as the template won't compile if the type doesn't have those methods.
However, if you want to check for them, then one way might be to use their addresses in some compile-time context, e.g
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 output 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 down if either of the required methods is overloaded, and naturally this still doesn't test whether these methods have a suitable prototype.
E.g perhaps you expect bool Init(int, int). You could use a static_cast to check for exact signature, but again this might place unnecessary restrictions on the type. For example, so what if some class has bool Init(long, long) instead)?
One way or another, this effort seems necessary only to make the error messages more obvious. However, I very much doubt that any message that you'd get otherwise without any concepts checks (a la "no suitable method Init to call with T = X when used here") is that bad.
No, this is not possible.
Templates are replaced with one type and not with many differents.
Consider creating a base class that all possible members have to inherit from and leave all templates out.
You basically with to introduce existential types, which is not supported in C++.
Not possible in the current standard. I believe it is possible through 'concepts' supposed (?) become standard in C++0x.
Well, I guess you could define a method that calls Init()
and Destroy()
on the template argument, and somehow call this method in debug mode.
Alternatively, you could define an interface, and cast to this interface in your template implementation. This could also be disabled in release mode.
Yes, you can.
It is, however, pretty complicated (advanced templates meta-programming) The whole concept is built on the "Substitution failure is not an error (SFINAE)" quality in C++ templates.
In essence, you can template using something like 'template <typename T, void (T::*)()>'
and instantiate using <T, T::Init>
in your vector. Unless the substitution exists you'll get a substitution error (the SFINAE principle is used here because most of the times you would like to use the constructor instead).
This is, of course, and over simplified description. I am sorry I can't currently provide a better one but you might want to take a look at this discussion. search for has_member and is_call_possible.
I hope it helps.
Oren
Actually, it's the opposite: If your template requires Init()
and Destroy()
, it's impossible to instantiate it with any type which does not have these two.
The only problem with templates in this regard is that the requirement is implicit (i.e., the template won't compile at the point those are required within the template), not explicit (i.e. the compiler tells you what's missing at the point of instantiation). Concepts were meant to fix that, but they were taken out of the next standard a while ago.
精彩评论