Created
February 6, 2016 23:26
-
-
Save lefticus/6fdccb18084a1a3410d5 to your computer and use it in GitHub Desktop.
Revisions
-
lefticus created this gist
Feb 6, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,122 @@ #include <iostream> #include <memory> #include <vector> #include <algorithm> #include <type_traits> template< class ... > using void_t = void; template< class T , class = void > struct is_dereferenceable : std::false_type { }; template< class T > struct is_dereferenceable<T, void_t<decltype( &std::remove_reference_t<T>::operator* )>> : std::true_type { typedef std::result_of_t<decltype(&std::remove_reference_t<T>::operator*)(T)> result; }; template< class T > struct is_dereferenceable<T, std::enable_if_t< !std::is_void<std::remove_pointer_t<T>>::value && std::is_pointer<std::remove_reference_t<T>>::value > > : std::true_type { typedef std::add_lvalue_reference_t<std::remove_pointer_t<std::remove_reference_t<T>>> result; }; template< class T > constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value; template< class T , class = void > struct has_arrow_operator : std::false_type { }; template< class T > struct has_arrow_operator<T, void_t<decltype( &std::decay_t<T>::operator-> )>> : std::true_type { typedef typename std::result_of_t<decltype(&std::decay_t<T>::operator->)(T)> result; }; template< class T > struct has_arrow_operator<T, std::enable_if_t<std::is_pointer<std::remove_reference_t<T>>::value>> : std::true_type { typedef std::remove_reference_t<T> result; }; template< class T > constexpr bool has_arrow_operator_v = has_arrow_operator<T>::value; template< class T , class = void > struct is_model_of_pointer : std::false_type { }; template< class T > struct is_model_of_pointer<T, std::enable_if_t< is_dereferenceable<T>() && has_arrow_operator<T>() && std::is_same< std::remove_pointer_t<typename has_arrow_operator<T>::result>, std::remove_reference_t<typename is_dereferenceable<T>::result> >::value > > : std::true_type { }; template< class T > constexpr bool is_model_of_pointer_v = is_model_of_pointer<T>::value; template<typename V> auto value_of(V &&v) -> std::enable_if_t<is_model_of_pointer_v<V>, decltype(*v)> { return *v; } template<typename V> auto value_of(V &&v) -> std::enable_if_t<!is_model_of_pointer<V>::value, V> { return std::forward<V>(v); } int main() { static_assert(is_dereferenceable<std::vector<int>::iterator>(), "iter"); static_assert(is_dereferenceable<std::vector<int>::const_iterator>(), "const_iter"); static_assert(is_dereferenceable<int*>(), "ptr"); static_assert(!is_dereferenceable<int>(), "value"); static_assert(is_dereferenceable<std::shared_ptr<int>>(), "shared_ptr"); static_assert(is_dereferenceable<std::unique_ptr<int>>(), "unique_ptr"); static_assert(!is_dereferenceable<void *>(), "void *"); static_assert(!is_dereferenceable<const void *>(), "const void *"); const std::array<int, 3> a{1,2,3}; const std::vector<int> v1{4,5,6}; const std::vector<std::shared_ptr<int>> v2{std::make_shared<int>(7),std::make_shared<int>(8),std::make_shared<int>(9)}; const std::vector<int *> v3{new int(10), new int(11), new int(12)}; const std::vector<std::unique_ptr<int>> v4 = [](){ std::vector<std::unique_ptr<int>> v; v.emplace_back(std::make_unique<int>(13)); v.emplace_back(std::make_unique<int>(14)); v.emplace_back(std::make_unique<int>(15)); return v; }(); const std::vector<std::vector<int>::const_iterator> v5{v1.begin()+2, v1.begin()+1, v1.begin()}; const auto printer = [](const auto &v){ std::cout << value_of(v) << '\n'; }; const auto print_all = [printer](const auto &c) { std::for_each(std::begin(c), std::end(c), printer); }; print_all(a); print_all(v1); print_all(v2); print_all(v3); print_all(v4); print_all(v5); }