Suppose I want to use std::conditional
to determine a type, if the type is a vector<...>
the return will be a vector<...>::size_type
and if not it will be int
. (just an example).
A naive way to use std::conditional
:
template<class V> struct is_vector : std::false_type{};
template<class T> struct is_vector<std::vector<T>> : std::true_type{};
template<class C>
using my_size_type = typename std::conditional<
not is_vector<C>::value,
int,
C::size_type // note that this line only makes sense when condition is false
>::type;
However this fails because if C
is say a double
, double::size_type
will give an error, even if the that is the evaluation of the second false option.
So, I am wonder if there is a sort of lazy_conditional
in which the false (or the second false) statement is not evaluated.
I found something here: https://mcmap.net/q/1093881/-lazy-evaluation but I don't know how to use it my example.
Note that I know how to get the same result without using std::conditional
:
template<class V> struct my_size_type{typedef int type;};
template<class T> struct my_size_type<std::vector<T>>{typedef std::vector<T>::size_type type;};
The question is if there is a lazy_conditional
that somehow encapsulated a std::conditional
that is short circuited.
After some trial error I manage to use the ideas in https://mcmap.net/q/1093881/-lazy-evaluation and get to this that follows. It also makes me think that it is not possible to write std::lazy_conditional
because C::size_type
cannot appear at all in any expression a priori, so two-step expressions are needed.
template<class C, bool B> struct false_case{
typedef void type;
};
template<class C> struct false_case<C, false>{
typedef typename C::size_type type;
};
template<class C>
using size_type = typename std::conditional<
not is_vector<C>::value,
int,
typename false_case<C, not is_vector<C>::value>::type
>::type;
I couldn't even condense this into a macro, because each case is different.
lazy_conditional<C, T, lazy_F>
. Anyway this also shows that free metafunction are better than member (have std::size_type_of<T>::type rather than rely on T::size_type) when possible (like free function is better than member functions for generic code). – Pasquil