Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template restrictions

Tags:

c++

templates

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
like image 809
Andrew Avatar asked Jun 17 '10 14:06

Andrew


People also ask

How will you restrict the template for a specific datatype?

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.

What is the main problem with templates C++?

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.

Are templates supported in C?

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.

What are disadvantages of using templates in C++?

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.


2 Answers

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.

like image 112
James Hopkin Avatar answered Oct 19 '22 18:10

James Hopkin


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>          ]
like image 23
obelix Avatar answered Oct 19 '22 18:10

obelix