Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: specifying a base class for a template parameter

Tags:

c++

templates

I need to design a framework that computes the result of a divide-et-conquer algorithm in parallel. In order to use the framework, the user needs to specify somehow the procedure that implements the "divide" phase (a function from T to T), the "conquer" phase (a function from D to D) and T and D themselves.

I've thought it would be nice to define two abstract classes, BaseDivide and BaseConquer, which declares a pure virtual method compute with the right types: that way I have a type which implements a well-defined concept (from the point of view of the framework) with the user-definable function included by means of derivation of the abstract classes.

I've thought to use templates to pass the types to the framework, so the user doesn't have to instantiate them in order to use the framework, so something like that:

template <typename T, typename D, typename Divide, typename Conquer> 
D compute(T arg);

My problem is that I want that Divide and Conquer to be derived types of BaseDivide and BaseConquer: there is a way to enforce it at compile time? Also: do you think I can achieve a similar result with a cleaner design?

like image 960
akappa Avatar asked May 04 '11 18:05

akappa


2 Answers

You could create the base classes like this:

struct BaseDivide {
    enum EnumDiv { derivedFromBaseDivide = true };
}

template <typename T, typename D, typename Divide, typename Conquer> 
    static_assert(D::derivedFromBaseDivide);
    D compute(T arg);

What is the purpose of the additional Divide and Conquer template parameters? Are you sure you need them?

like image 142
Gunther Piez Avatar answered Oct 07 '22 09:10

Gunther Piez


Use Boost.EnabelIf to trigger SFINAE when your types don't fulfill your requirement. Checking if T is derived from U is doen with boost::is_base_of :

#include <boost/type_traits/is_base_of.hpp>
#include <boost/enable_if.hpp>

template <typename T, typename D, typename Divide, typename Conquer> 
typename boost::
enable_if_c< boost::is_base_of<BaseDivide,Divide>::value 
          && boost::is_base_of<BaseConquer,Conquer>::value
          ,D
          >::type
compute(T arg);
like image 36
Joel Falcou Avatar answered Oct 07 '22 08:10

Joel Falcou