← Back
Editing: combined.hpp
#ifndef PYTHONIC_INCLUDE_TYPES_COMBINED_HPP #define PYTHONIC_INCLUDE_TYPES_COMBINED_HPP #include "pythonic/include/types/traits.hpp" PYTHONIC_NS_BEGIN namespace types { template <class... Types> struct variant_functor; } PYTHONIC_NS_END /* type inference stuff */ template <class... Types> struct __combined; template <class T> struct __combined<T> { using type = T; }; template <class T0, class T1, class T2, class... Types> struct __combined<T0, T1, T2, Types...> { // This is less efficient that doing a binary split, but it's not equivalent // as the lhs dominates the rhs (a.k.a __combined is neither commutative nor // associative) using type = typename __combined<typename __combined<T0, T1>::type, T2, Types...>::type; }; template <class T0, class T1> struct __combined<T0, T1> { // callable -> functor template <class F0, class F1> static pythonic::types::variant_functor<F0, F1> get(std::integral_constant<bool, true>); // operator+ exists -> deduce type template <class F0, class F1> static decltype(std::declval<F0>() + std::declval<F1>()) get(std::integral_constant<bool, false>); // operator+ does not exists -> pick first one, better than error // note that this is needed because broadcasting is too complex to be modeled // by our clumsy type inference scheme // so we sometime endup with __combined<indexable_container<...>, int> which // only makes sense when broadcasting // fortunately, broadcasting is only supported by ndarray, && we already // ignore __combined for ndarray // so the only thing to do in such situations is « ! throw an error » template <class F0, class F1> static F0 get(...); using type = typename std::conditional< std::is_same<T0, T1>::value, T0, decltype(get<T0, T1>(std::integral_constant< bool, pythonic::types::is_callable<T0>::value && pythonic::types::is_callable<T1>::value>()))>::type; }; template <class T0, class T1> struct __combined<const T0, T1> { using type = typename std::add_const<typename __combined<T0, T1>::type>::type; }; template <class T0, class T1> struct __combined<T0, const T1> { using type = typename std::add_const<typename __combined<T0, T1>::type>::type; }; template <class T0, class T1> struct __combined<T0 &, T1> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 &&, T1> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 const &, T1> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0, T1 &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0, T1 &&> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0, T1 const &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<const T0, T1 const &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<const T0, T1 &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<const T0, T1 &&> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 &, T1 const> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 &&, T1 const> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 const &, T1 const> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 &, T1 const &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 &&, T1 const &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 const &, T1 &> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 const &, T1 &&> { using type = typename __combined<T0, T1>::type; }; template <class T0, class T1> struct __combined<T0 &, T1 &> { using type = typename std::add_lvalue_reference< typename __combined<T0, T1>::type>::type; }; template <class T0, class T1> struct __combined<T0 &&, T1 &&> { using type = typename std::add_rvalue_reference< typename __combined<T0, T1>::type>::type; }; template <class T0, class T1> struct __combined<const T0, const T1> { using type = typename std::add_const<typename __combined<T0, T1>::type>::type; }; template <class T0, class T1> struct __combined<const T0 &, const T1 &> { using type = typename std::add_lvalue_reference< typename std::add_const<typename __combined<T0, T1>::type>::type>::type; }; template <class T> class container { public: using value_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type; private: container(); }; template <class K, class V> class indexable_container { public: using key_type = typename std::remove_cv<typename std::remove_reference<K>::type>::type; using value_type = typename std::remove_cv<typename std::remove_reference<V>::type>::type; private: indexable_container(); }; template <class T> class dict_container { public: using value_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type; private: dict_container(); }; template <class T> class indexable { public: using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type; private: indexable(); }; template <class T> class indexable_dict { public: using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type; private: indexable_dict(); }; template <class K0, class V0, class K1, class V1> struct __combined<indexable_container<K0, V0>, indexable_container<K1, V1>> { using type = indexable_container<typename __combined<K0, K1>::type, typename __combined<V0, V1>::type>; }; template <class K, class V> struct __combined<indexable<K>, indexable<V>> { using type = indexable<typename __combined<K, V>::type>; }; template <class K, class V> struct __combined<indexable<K>, container<V>> { using type = indexable_container<K, V>; }; template <class V, class K> struct __combined<container<V>, indexable<K>> { using type = indexable_container<K, V>; }; template <class K, class V, class W> struct __combined<indexable_container<K, V>, container<W>> { using type = indexable_container<K, typename __combined<V, W>::type>; }; template <class V, class K, class W> struct __combined<container<W>, indexable_container<K, V>> { using type = indexable_container<K, typename __combined<V, W>::type>; }; template <class K1, class V1, class K2> struct __combined<indexable_container<K1, V1>, indexable<K2>> { using type = indexable_container<typename __combined<K1, K2>::type, V1>; }; template <class K1, class V1, class K2> struct __combined<indexable<K2>, indexable_container<K1, V1>> { using type = indexable_container<typename __combined<K1, K2>::type, V1>; }; template <class A, class B> struct __combined<container<A>, container<B>> { using type = container<typename __combined<A, B>::type>; }; /* special handling for functors * as it's based on a trait, template specialization cannot be used * so we rely on operator+ specialization * { */ template <class T, class... Types> struct __combined<T, pythonic::types::variant_functor<Types...>> { using type = pythonic::types::variant_functor<T, Types...>; }; template <class T, class... Types> struct __combined<pythonic::types::variant_functor<Types...>, T> { using type = pythonic::types::variant_functor<T, Types...>; }; template <class... Types0, class... Types1> struct __combined<pythonic::types::variant_functor<Types0...>, pythonic::types::variant_functor<Types1...>> { using type = pythonic::types::variant_functor<Types0..., Types1...>; }; /* } */ /* mimic numpy behavior { */ #define SCALAR_COMBINER(Type) \ template <> \ struct __combined<Type, Type> { \ using type = Type; \ }; SCALAR_COMBINER(bool) SCALAR_COMBINER(uint8_t) SCALAR_COMBINER(int8_t) SCALAR_COMBINER(uint16_t) SCALAR_COMBINER(int16_t) SCALAR_COMBINER(uint32_t) SCALAR_COMBINER(int32_t) SCALAR_COMBINER(uint64_t) SCALAR_COMBINER(int64_t) #undef SCALAR_COMBINER #endif
Save File
Cancel