I wondering is there any way to set restrictions on template class?
Specify that every type substituted in template must have specific ancestor (realize some interface).
template < class B > //and every B must be a child of abstract C
class A {
public:
B * obj;
int f() {
return B::x + this->obj->f();
}
};
Like => in haskell
func :: (Ord a, Show b) => a -> b -> c
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
C++ templates can't use normal run-time C++ code in the process of expanding, and suffer for it: for instance, the C++ factorial program is limited in that it produces 32-bit integers rather than arbitrary-length bignums.
The main type of templates that can be implemented in C are static templates. Static templates are created at compile time and do not perform runtime checks on sizes, because they shift that responsibility to the compiler.
First, many compilers historically have very poor support for templates, so the use of templates can make code somewhat less portable. Second, almost all compilers produce confusing, unhelpful error messages when errors are detected in template code. This can make templates difficult to develop.
A future version of C++ will support this natively using concepts (which didn't make it into C++11).
One way to approach the problem is to use specialisation on a dummy template parameter:
class C {};
template <class B, class dummy=void>
class A;
template <class B>
class A<B, typename enable_if<is_base_and_derived<C, B> >::type>
{
// class definition here
};
struct D : C {};
A<D> d; // fine
A<int> n; // compile error - undefined class A<B>
I've put stand-alone definitions of enable_if
and is_base_and_derived
here.
The following works in VC10 using static_assert. I've just seen this used and haven't really dug around much into what static_assert actually does - perhaps someone else can answer that.
#include <type_traits>
class Base
{
};
class Derived : public Base
{
};
class SomeRandomClass
{
};
template<typename T>
class A
{
static_assert(std::tr1::is_base_of<Base, T>::value, "T not derived from Base");
};
int _tmain(int argc, _TCHAR* argv[])
{
argc; argv;
//
// This will compile
A<Derived> a;
//
// This will throw a compilation error
A<SomeRandomClass> b;
return 0;
}
The compiler output being:
1>d:\temp\aaa\aaa\aaa.cpp(25): error C2338: T not derived from Base
1> d:\temp\aaa\aaa\aaa.cpp(41) : see reference to class template instantiation 'A<T>' being compiled
1> with
1> [
1> T=SomeRandomClass
1> ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With