
.. _program_listing_file__home_david_GitProjects_h5pp_h5pp_include_h5pp_details_h5ppTypeSfinae.h:

Program Listing for File h5ppTypeSfinae.h
=========================================

|exhale_lsh| :ref:`Return to documentation for file <file__home_david_GitProjects_h5pp_h5pp_include_h5pp_details_h5ppTypeSfinae.h>` (``/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppTypeSfinae.h``)

.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS

.. code-block:: cpp

   #pragma once
   #include "h5ppEigen.h"
   #include "h5ppOptional.h"
   #include "h5ppTypeCompound.h"
   #include <array>
   #include <sstream>
   #include <string>
   #include <string_view>
   #include <type_traits>
   #include <vector>
   
   namespace h5pp::type::sfinae {
   
       // SFINAE detection
       template<typename...>
       struct print_type_and_exit_compile_time;
   
       template<typename T>
       constexpr auto type_name() {
           std::string_view name, prefix, suffix;
   #ifdef __clang__
           name   = __PRETTY_FUNCTION__;
           prefix = "auto h5pp::type::sfinae::type_name() [T = ";
           suffix = "]";
   #elif defined(__GNUC__)
           name   = __PRETTY_FUNCTION__;
           prefix = "constexpr auto h5pp::type::sfinae::type_name() [with T = ";
           suffix = "]";
   #elif defined(_MSC_VER)
           name   = __FUNCSIG__;
           prefix = "auto __cdecl h5pp::type::sfinae::type_name<";
           suffix = ">(void)";
   #endif
           name.remove_prefix(prefix.size());
           name.remove_suffix(suffix.size());
           return name;
       }
   
       template<typename T, typename = std::void_t<>>
       struct has_size : public std::false_type {};
       template<typename T>
       struct has_size<T, std::void_t<decltype(std::declval<T>().size())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_size_v = has_size<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_resize0 : public std::false_type {};
       template<typename T>
       struct has_resize0<T, std::void_t<decltype(std::declval<T>().resize())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_resize0_v = has_resize0<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_resize : public std::false_type {};
       template<typename T>
       struct has_resize<T, std::void_t<decltype(std::declval<T>().resize(0))>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_resize_v = has_resize<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_resize2 : public std::false_type {};
       template<typename T>
       struct has_resize2<T, std::void_t<decltype(std::declval<T>().resize(0, 0))>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_resize2_v = has_resize2<T>::value;
   
       template<typename T, auto rank, typename = std::void_t<>>
       struct has_resizeN : public std::false_type {};
       template<typename T, auto rank>
       struct has_resizeN<T, rank, std::void_t<decltype(std::declval<T>().resize(std::declval<std::array<long, rank>>()))>> : public std::true_type {};
       template<typename T, auto rank>
       inline constexpr bool has_resizeN_v = has_resizeN<T, rank>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_data : public std::false_type {};
       template<typename T>
       struct has_data<T, std::void_t<decltype(std::declval<T>().data())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_data_v = has_data<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_value_type : public std::false_type {};
       template<typename T>
       struct has_value_type<T, std::void_t<typename T::value_type>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_value_type_v = has_value_type<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_c_str : public std::false_type {};
       template<typename T>
       struct has_c_str<T, std::void_t<decltype(std::declval<T>().c_str())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_c_str_v = has_c_str<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_imag : public std::false_type {};
       template<typename T>
       struct has_imag<T, std::void_t<decltype(std::declval<T>().imag())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_imag_v = has_imag<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_Scalar : public std::false_type {};
       template<typename T>
       struct has_Scalar<T, std::void_t<typename T::Scalar>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_Scalar_v = has_Scalar<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_NumIndices : public std::false_type {};
       template<typename T>
       struct has_NumIndices<T, std::void_t<decltype(std::declval<T>().NumIndices)>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_NumIndices_v = has_NumIndices<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_dimensions : public std::false_type {};
       template<typename T>
       struct has_dimensions<T, std::void_t<decltype(std::declval<T>().dimensions())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_dimensions_v = has_dimensions<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_x : public std::false_type {};
       template<typename T>
       struct has_x<T, std::void_t<decltype(std::declval<T>().x)>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_x_v = has_x<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_y : public std::false_type {};
       template<typename T>
       struct has_y<T, std::void_t<decltype(std::declval<T>().y)>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_y_v = has_y<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct has_z : public std::false_type {};
       template<typename T>
       struct has_z<T, std::void_t<decltype(std::declval<T>().z)>> : public std::true_type {};
       template<typename T>
       inline constexpr bool has_z_v = has_z<T>::value;
   
       template<typename Test, template<typename...> class Ref>
       struct is_specialization : std::false_type {};
       template<template<typename...> class Ref, typename... Args>
       struct is_specialization<Ref<Args...>, Ref> : std::true_type {};
   
       template<typename T>
       struct is_std_vector : public std::false_type {};
       template<typename T>
       struct is_std_vector<std::vector<T>> : public std::true_type {};
       template<typename T>
       inline constexpr bool is_std_vector_v = is_std_vector<T>::value;
   
       template<typename T>
       struct is_std_array : public std::false_type {};
       template<typename T, auto N>
       struct is_std_array<std::array<T, N>> : public std::true_type {};
       template<typename T>
       inline constexpr bool is_std_array_v = is_std_array<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct is_streamable : std::false_type {};
       template<typename T>
       struct is_streamable<T, std::void_t<decltype(std::declval<std::stringstream &> << std::declval<T>())>> : public std::true_type {};
       template<typename T>
       inline constexpr bool is_streamable_v = is_streamable<T>::value;
   
       template<typename T, typename = std::void_t<>>
       struct is_iterable : public std::false_type {};
       template<typename T>
       struct is_iterable<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()), typename T::value_type>> : public std::true_type {};
       template<typename T>
       inline constexpr bool is_iterable_v = is_iterable<T>::value;
   
       template<typename T>
       struct is_integral_iterable {
           private:
           template<typename U>
           static constexpr bool test() {
               if constexpr(is_iterable_v<U> and has_value_type_v<U>)
                   return std::is_integral_v<typename T::value_type>;
               else
                   return false;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
       template<typename T>
       inline constexpr bool is_integral_iterable_v = is_integral_iterable<T>::value;
   
       template<typename T>
       struct is_integral_iterable_or_num {
           private:
           template<typename U>
           static constexpr bool test() {
               if constexpr(is_integral_iterable_v<T>) return true;
               return std::is_integral_v<T>;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
       template<typename T>
       inline constexpr bool is_integral_iterable_or_num_v = is_integral_iterable_or_num<T>::value;
   
       template<typename T>
       using enable_if_is_integral_iterable = std::enable_if_t<is_integral_iterable_v<T>>;
   
       template<typename T>
       using enable_if_is_integral_iterable_or_num = std::enable_if_t<is_integral_iterable_or_num_v<T>>;
   
       template<typename T>
       using enable_if_is_integral_iterable_or_nullopt = std::enable_if_t<is_integral_iterable_or_num_v<T> or std::is_same_v<T, std::nullopt_t>>;
   
   
   
       template<typename T>
       using enable_if_is_iterable_or_nullopt = std::enable_if_t<is_iterable_v<T> or std::is_same_v<T, std::nullopt_t>>;
   
   
   
       template<typename T>
       using enable_if_is_h5_loc = std::enable_if_t<std::is_same_v<T,hid::h5f> or std::is_same_v<T, hid::h5g> or std::is_same_v<T, hid::h5o> or std::is_same_v<T, hid_t>>;
       template<typename T>
       using enable_if_is_h5_loc_or_hid_t = std::enable_if_t< std::is_same_v<T,hid::h5f> or std::is_same_v<T, hid::h5g> or std::is_same_v<T, hid::h5o> or std::is_same_v<T, hid_t> or std::is_same_v<T,hid_t>>;
       template<typename T>
       using enable_if_is_h5_link = std::enable_if_t< std::is_same_v<T,hid::h5f> or std::is_same_v<T, hid::h5d> or std::is_same_v<T, hid::h5g> or std::is_same_v<T, hid::h5o> or std::is_same_v<T, hid_t>>;
       template<typename T>
       using enable_if_is_h5_link_or_hid_t = std::enable_if_t< std::is_same_v<T,hid::h5f> or std::is_same_v<T, hid::h5d> or std::is_same_v<T, hid::h5g> or std::is_same_v<T, hid::h5o> or std::is_same_v<T, hid_t> or std::is_same_v<T,hid_t>>;
   
   
   
       template<typename T>
       struct is_text {
           private:
           template<typename U>
           static constexpr bool test() {
               using DecayType = typename std::decay<U>::type;
               // No support for wchar_t, char16_t and char32_t
               if constexpr(has_c_str_v<DecayType>) return true;
               if constexpr(std::is_same_v<DecayType, std::string>) return true;
               if constexpr(std::is_same_v<DecayType, std::string_view>) return true;
               if constexpr(std::is_same_v<DecayType, const char *>) return true;
               if constexpr(std::is_same_v<DecayType, const char[]>) return true;
               if constexpr(std::is_same_v<DecayType, char *>) return true;
               if constexpr(std::is_same_v<DecayType, char[]>) return true;
               if constexpr(std::is_same_v<DecayType, char>)
                   return true;
               else
                   return false;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
   
       template<typename T>
       inline constexpr bool is_text_v = is_text<T>::value;
   
       template<typename T>
       struct has_text {
           private:
           template<typename U>
           static constexpr bool test() {
               using DecayType = typename std::decay<U>::type;
               if constexpr(is_text_v<U>) return false;
               if constexpr(std::is_array_v<DecayType>) return is_text_v<typename std::remove_all_extents_t<DecayType>>;
               if constexpr(std::is_pointer_v<DecayType>) return is_text_v<typename std::remove_pointer_t<DecayType>>;
               if constexpr(has_value_type_v<DecayType>) return is_text_v<typename DecayType::value_type>;
               return false;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
       template<typename T>
       inline constexpr bool has_text_v = has_text<T>::value;
   
       template<typename Outer, typename Inner>
       struct is_container_of {
           private:
           template<typename O, typename I>
           static constexpr bool test() {
               //            using Od = typename std::decay<O>::type;
               if constexpr(is_iterable_v<O>) {
                   if constexpr(has_value_type_v<O>) {
                       using I_lhs = typename std::decay<I>::type;
                       using I_rhs = typename std::decay<typename O::value_type>::type;
                       return std::is_same_v<I_lhs, I_rhs>;
                   }
               }
               return false;
           }
   
           public:
           static constexpr bool value = test<Outer, Inner>();
       };
   
       template<typename Outer, typename Inner>
       inline constexpr bool is_container_of_v = is_container_of<Outer, Inner>::value;
   
       template<typename T>
       struct is_std_complex : public std::false_type {};
       template<typename T>
       struct is_std_complex<std::complex<T>> : public std::true_type {};
       template<typename T>
       inline constexpr bool is_std_complex_v = is_std_complex<T>::value;
   
       template<typename T>
       struct is_Scalar2 {
           private:
           static constexpr bool test() {
               if constexpr(has_x_v<T> and has_y_v<T> and not has_z_v<T>) {
                   constexpr size_t t_size = sizeof(T);
                   constexpr size_t x_size = sizeof(T::x);
                   constexpr size_t y_size = sizeof(T::y);
                   return t_size == x_size + y_size;
               } else {
                   return false;
               }
           }
   
           public:
           static constexpr bool value = test();
       };
       template<typename T>
       inline constexpr bool is_Scalar2_v = is_Scalar2<T>::value;
   
       template<typename T>
       struct is_Scalar3 {
           private:
           static constexpr bool test() {
               if constexpr(has_x_v<T> and has_y_v<T> and has_z_v<T>) {
                   constexpr size_t t_size = sizeof(T);
                   constexpr size_t x_size = sizeof(T::x);
                   constexpr size_t y_size = sizeof(T::y);
                   constexpr size_t z_size = sizeof(T::z);
                   return t_size == x_size + y_size + z_size;
               } else {
                   return false;
               }
           }
   
           public:
           static constexpr bool value = test();
       };
       template<typename T>
       inline constexpr bool is_Scalar3_v = is_Scalar3<T>::value;
   
       template<typename T1, typename T2>
       constexpr bool is_Scalar2_of_type() {
           if constexpr(is_Scalar2_v<T1>) return std::is_same<decltype(T1::x), T2>::value;
           return false;
       }
   
       template<typename T>
       constexpr bool is_ScalarN() {
           return is_Scalar2_v<T> or is_Scalar3_v<T>;
       }
   
       template<typename T1, typename T2>
       constexpr bool is_Scalar3_of_type() {
           if constexpr(is_Scalar3_v<T1>)
               return std::is_same<decltype(T1::x), T2>::value;
           else
               return false;
       }
   
   #ifdef H5PP_EIGEN3
   
       template<typename T>
       using is_eigen_matrix = std::is_base_of<Eigen::MatrixBase<std::decay_t<T>>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_matrix_v = is_eigen_matrix<T>::value;
       template<typename T>
       using is_eigen_array = std::is_base_of<Eigen::ArrayBase<std::decay_t<T>>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_array_v = is_eigen_array<T>::value;
       template<typename T>
       using is_eigen_tensor = std::is_base_of<Eigen::TensorBase<std::decay_t<T>, Eigen::ReadOnlyAccessors>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_tensor_v = is_eigen_tensor<T>::value;
       template<typename T>
       using is_eigen_dense = std::is_base_of<Eigen::DenseBase<std::decay_t<T>>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_dense_v = is_eigen_dense<T>::value;
       template<typename T>
       using is_eigen_map = std::is_base_of<Eigen::MapBase<std::decay_t<T>, Eigen::ReadOnlyAccessors>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_map_v = is_eigen_map<T>::value;
       template<typename T>
       using is_eigen_plain = std::is_base_of<Eigen::PlainObjectBase<std::decay_t<T>>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_plain_v = is_eigen_plain<T>::value;
       template<typename T>
       using is_eigen_base = std::is_base_of<Eigen::EigenBase<std::decay_t<T>>, std::decay_t<T>>;
       template<typename T>
       inline constexpr bool is_eigen_base_v = is_eigen_base<T>::value;
       template<typename T>
       struct is_eigen_core : public std::false_type {};
       template<typename T, int rows, int cols, int StorageOrder>
       struct is_eigen_core<Eigen::Matrix<T, rows, cols, StorageOrder>> : public std::true_type {};
       template<typename T, int rows, int cols, int StorageOrder>
       struct is_eigen_core<Eigen::Array<T, rows, cols, StorageOrder>> : public std::true_type {};
       template<typename T>
       inline constexpr bool is_eigen_core_v = is_eigen_core<T>::value;
       template<typename T>
       struct is_eigen_any {
           static constexpr bool value = is_eigen_base<T>::value or is_eigen_tensor<T>::value;
       };
       template<typename T>
       inline constexpr bool is_eigen_any_v = is_eigen_any<T>::value;
       template<typename T>
       struct is_eigen_contiguous {
           static constexpr bool value = is_eigen_any<T>::value and has_data<T>::value;
       };
       template<typename T>
       inline constexpr bool is_eigen_contiguous_v = is_eigen_contiguous<T>::value;
   
       template<typename T>
       class is_eigen_1d {
           private:
           template<typename U>
           static constexpr auto test() {
               if constexpr(is_eigen_map<U>::value) return test<typename U::PlainObject>();
               if constexpr(is_eigen_dense<U>::value) return U::RowsAtCompileTime == 1 or U::ColsAtCompileTime == 1;
               if constexpr(is_eigen_tensor<U>::value and has_NumIndices<U>::value)
                   return U::NumIndices == 1;
               else
                   return false;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
       template<typename T>
       inline constexpr bool is_eigen_1d_v = is_eigen_1d<T>::value;
   
       template<typename T>
       class is_eigen_colmajor {
           template<typename U>
           static constexpr bool test() {
               if constexpr(is_eigen_base<U>::value) return not U::IsRowMajor;
               if constexpr(is_eigen_tensor<U>::value)
                   return Eigen::ColMajor == static_cast<Eigen::StorageOptions>(U::Layout);
               else
                   return false;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
       template<typename T>
       inline constexpr bool is_eigen_colmajor_v = is_eigen_colmajor<T>::value;
   
       template<typename T>
       class is_eigen_rowmajor {
           template<typename U>
           static constexpr bool test() {
               if constexpr(is_eigen_base<U>::value) return U::IsRowMajor;
               if constexpr(is_eigen_tensor<U>::value)
                   return Eigen::RowMajor == static_cast<Eigen::StorageOptions>(U::Layout);
               else
                   return false;
           }
   
           public:
           static constexpr bool value = test<T>();
       };
       template<typename T>
       inline constexpr bool is_eigen_rowmajor_v = is_eigen_rowmajor<T>::value;
   
   #endif
   
   }
