Предположим, я хочу использовать std::conditional
определить тип, если тип vector<...>
возвращение будет vector<...>::size_type
а если нет то будет int
, (просто пример).
Наивный способ использования 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;
Однако это не удается, потому что если C
это сказать double
, double::size_type
выдаст ошибку, даже если это оценка второй ложной опции.
Итак, мне интересно, если есть lazy_conditional
в котором ложное (или второе ложное) утверждение не оценивается.
Я нашел кое-что здесь: https://stackoverflow.com/a/5317659/225186 но я не знаю, как использовать это мой пример.
Обратите внимание, что я знаю, как получить тот же результат без использования 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;};
Вопрос в том, есть ли lazy_conditional
что-то инкапсулировало std::conditional
это короткое замыкание.
После некоторой пробной ошибки мне удается использовать идеи в https://stackoverflow.com/a/5317659/225186 и получить к этому следующее. Это также заставляет меня думать, что это не возможно, чтобы написать std::lazy_conditional
так как C::size_type
не может появляться вообще ни в одном выражении априори, поэтому необходимы двухэтапные выражения.
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;
Я даже не мог сжать это в макрос, потому что каждый случай индивидуален.
Вам нужен уровень косвенности.
template<class T> struct identity { using type = T; };
template<class C>
struct size_type_of : identity<typename C::size_type> { };
template<class C>
using size_type = typename std::conditional<not is_vector<C>::value,
identity<int>,
size_type_of<C>>::type::type;
Дело в том, чтобы отложить рассмотрение C::size_type
(путем создания size_type_of<C>
), пока вы не знаете, что есть.
Если то, что вы действительно хотите сделать, этоC::size_type
если он существует, int
иначе «, то std::experimental::detected_or_t
твой друг:
template<class C>
using size_type_t = typename C::size_type;
template<class C>
using size_type_or_default = std::experimental::detected_or_t<int, size_type_t, C>;
Других решений пока нет …