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;
};
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.
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.
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.
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 typename
s 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;
};
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