type_traits/type_member.hh

00001 // This file is a part of Catsfoot.
00002 // Copyright (C) 2011  Uni Research
00003 //
00004 // This program is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser Public License as published by
00006 // the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser Public License
00015 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #ifndef __TYPE_MEMBER_HH
00018 # define __TYPE_MEMBER_HH
00019 
00020 namespace catsfoot {
00022   struct undefined_member_type {};
00023 }
00024 
00032 # define DEF_TYPE_MEMBER_PREDICATE(X...)                                \
00033   namespace details {                                                   \
00034     template <typename T>                                               \
00035     std::false_type has_member_##X##_helper                             \
00036     (catsfoot::details::try_second, const T&) {                         \
00037       static_assert(catsfoot::details::always_false<T>::value,          \
00038                     "Cannot use this function");                        \
00039       return 0;                                                         \
00040     }                                                                   \
00041     template <typename T,                                               \
00042               typename = typename T::X>                                 \
00043     std::true_type has_member_##X##_helper                              \
00044     (catsfoot::details::try_first, const T&) {                          \
00045       static_assert(catsfoot::details::always_false<T>::value,          \
00046                     "Cannot use this function");                        \
00047       return 0;                                                         \
00048     }                                                                   \
00049     template <typename T>                                               \
00050     struct has_member_##X##_real_map {                                  \
00051       typedef typename T::X member_type;                                \
00052     };                                                                  \
00053     template <typename>                                                 \
00054     struct has_member_##X##_bad_map {                                   \
00055       typedef catsfoot::undefined_member_type member_type;              \
00056     };                                                                  \
00057   }                                                                     \
00058   template <typename T>                                                 \
00059   struct has_member_##X:                                                \
00060     public catsfoot::identity                                           \
00061   <decltype(details::                                                   \
00062             has_member_##X##_helper                                     \
00063             (catsfoot::details::try_first(), std::declval<T>()))>       \
00064   ::type {                                                              \
00065     typedef typename catsfoot::identity                                 \
00066       <decltype(details::                                               \
00067                 has_member_##X##_helper                                 \
00068                 (catsfoot::details::try_first(), std::declval<T>()))>   \
00069       ::type                                                            \
00070       super;                                                            \
00071     typedef typename                                                    \
00072       std::conditional<super::value,                                    \
00073                        details::has_member_##X##_real_map<T>,           \
00074                        details::has_member_##X##_bad_map<T> >           \
00075       ::type::member_type member_type;                                  \
00076   };                                                                    \
00077   template <>                                                           \
00078   struct has_member_##X<void>:                                          \
00079     public std::false_type {                                            \
00080     typedef ::catsfoot::undefined_member_type member_type;              \
00081   };
00082 
00083 #endif