Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a template with derived behavior?

I have a template Conditional which returns value according to the boolean expression:

template<bool C, typename C1, typename C2>
struct Conditional {
};

template<typename C1, typename C2>
struct Conditional<true, C1, C2> {
    typedef C1 value;
};

template<typename C1, typename C2>
struct Conditional<false, C1, C2> {
    typedef C2 value;
};
<Conditional<(0 != 1), Int<0>, Int<1>>::value; // Int<0>
<Conditional<(0 == 1), Int<0>, Int<1>>::value, // Int<1>

I want to make a ConditionalInteger template where his behavior derives from Condition

ConditionalInteger<(0 != 1), 0, 1>::value == 0; // true
ConditionalInteger<(0 == 1), 0, 1>::value == 1  // false

With straight forward approach it works:

template<bool C, int N1, int N2>
struct ConditionalInteger {
};

template<int N1, int N2>
struct ConditionalInteger<true,N1,N2> {
    static constexpr int value = N1;
};

template<int N1, int N2>
struct ConditionalInteger<false,N1,N2> {
    static constexpr int value = N2;
};

How do I implement it using Conditional?

With the next try, I get an error:

No type named ‘value’ in ‘struct IntWrapper<0>’

template<int N>
struct IntWrapper {
    static constexpr int value = N;
};

template<bool C, int N1, int N2>
struct ConditionalInteger {
    using value = typename Conditional<C, typename IntWrapper<N1>::value, typename IntWrapper<N2>::value>::value;
};
like image 990
Dennis Vash Avatar asked Jun 25 '19 10:06

Dennis Vash


People also ask

Can a derived class be template?

If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class. We can use this facility to build generic versions of the Class Adapter Pattern – using a derived template class to modify the interface of the base class.

What is a template example?

A template is a form, mold or pattern used as a guide to make something. Here are some examples of templates: Website design. Creating a document. Knitting a sweater.

How do you declare a class template in C++?

Class Template Declarationtemplate <class T> class className { private: T var; ... .. ... public: T functionName(T arg); ... .. ... }; In the above declaration, T is the template argument which is a placeholder for the data type used, and class is a keyword.


1 Answers

I guess this is what you want:

template<bool C, int N1, int N2>
struct ConditionalInteger {
    static constexpr int value = 
        Conditional<C, IntWrapper<N1>, IntWrapper<N2>>::value::value;
};

static_assert(ConditionalInteger<true, 2, 3>::value == 2);
static_assert(ConditionalInteger<false, 2, 3>::value == 3);

Conditional accepts types, and you give it two types: IntWrapper<N1> and IntWrapper<N2>. It returns a type Conditional<C, IntWrapper<N1>, IntWrapper<N2>>::value, which is IntWrapper<N>. Then you extract N from this type with one more ::value. You don't need typenames here.

You can also derive ConditionalInteger from IntWrapper:

template<bool C, int N1, int N2>
struct ConditionalInteger : IntWrapper<
    Conditional<C, IntWrapper<N1>, IntWrapper<N2>>::value::value> {};

More verbose implementation:

template<bool C, int N1, int N2>
struct ConditionalInteger {
    using Int = typename Conditional<C, IntWrapper<N1>, IntWrapper<N2>>::value;
    static constexpr int value = Int::value;
};
like image 62
Evg Avatar answered Oct 12 '22 03:10

Evg