I have Conditional
template
template<bool C, typename ...>
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;
};
Which seems to work as expected:
<Conditional<(0 != 1), Int<0>, Int<1>>::value; // Int<0>
<Conditional<(0 == 1), Int<0>, Int<1>>::value, // Int<1>
But it evaluates all values before returning:
template<typename G, typename M>
struct DoMove {
private:
constexpr static bool _isRLMove = (M::direction == Direction::LEFT || M::direction == Direction::RIGHT);
public:
using result = typename Conditional<
_isRLMove, typename DoMoveRL<G, M>::result, typename DoMoveUD<G, M>::result>::value;
// ^ when _isRLMove == false evaluates this
};
Which causes compile errors from DoMoveRL
.
How can one evaluate according to condition? What am I missing here?
As we all programmers know if or if else condition is used to create conditional statements so in angular template we can also use the if else but for elseif there is no direct way but we can use alternate way.
ng-container serves as a container for elements which can also accept structural directives but is not rendered to the DOM, while ng-template allows you to create template content that is not rendered until you specifically (conditionally or directly) add it to the DOM.
DoMoveRL<G, M>::result
forces instantiation of DoMoveRL<G, M>
.
You might delay the retrieval of result
to avoid to force instantiation:
template<typename G, typename M>
struct DoMove {
private:
constexpr static bool _isRLMove = (M::direction == Direction::LEFT
|| M::direction == Direction::RIGHT);
public:
using result = typename Conditional<
_isRLMove, DoMoveRL<G, M>, DoMoveUD<G, M>>::value::result;
};
There are a couple ways you could go about this. Traditionally, add a layer of indirection (live example):
template<bool C, template<typename ...> class...>
struct Conditional {
};
template<template<typename...> class C1, template<typename...> class C2>
struct Conditional<true, C1, C2> {
template<typename... Ts>
using apply = C1<Ts...>;
};
template<template<typename...> class C1, template<typename...> class C2>
struct Conditional<false, C1, C2> {
template<typename... Ts>
using apply = C2<Ts...>;
};
using result = typename Conditional<_isRLMove, DoMoveRL, DoMoveUD>::template apply<G, M>::result;
You can simplify this a bit if instantiating the templates themselves is fine and only accessing result
breaks. I've accounted for the templates themselves breaking.
In C++17, you can use if constexpr
if you like that better (live example):
template<typename T> struct type_val { using type = T; };
static auto choose_type() {
if constexpr (_isRLMove) {
return type_val<typename DoMoveRL<G, M>::result>{};
} else {
return type_val<typename DoMoveUD<G, M>::result>{};
}
}
using result = typename decltype(choose_type())::type;
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