type_traits/is_callable.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 IS_CALLABLE_HH
00018 # define IS_CALLABLE_HH
00019 
00020 # include <type_traits>
00021 # include <memory>
00022 # include "try_first.hh"
00023 # include "always_false.hh"
00024 # include "../concept/concept_tools.hh"
00025 # include "../type_traits/identity.hh"
00026 
00027 namespace catsfoot {
00028 
00030   template <typename T>
00031   struct undefined_return {};
00032 
00033   namespace details {
00035     template <typename T, typename... U>
00036     std::false_type is_callable_helper(try_second, T&&, U&&...) {
00037       static_assert(always_false<T>::value,
00038                     "Cannot use this function");
00039       return 0;
00040     }
00041 
00043     template <typename T, typename... U,
00044               typename =
00045               decltype(std::declval<T>()(std::declval<U>()...))>
00046     std::true_type is_callable_helper(try_first, T&&, U&&...) {
00047       static_assert(always_false<T>::value,
00048                     "Cannot use this function");
00049       return 0;
00050     }
00051 
00053     template <typename T>
00054     struct callable_real_map {};
00055 
00057     template <typename T>
00058     struct callable_bad_map {};
00059 
00061     template <typename T, typename... U>
00062     struct callable_real_map<T(U...)> {
00063       typedef decltype(std::declval<T>()(std::declval<U>()...))
00064       result_type;
00065     };
00066 
00068     template <typename T, typename... U>
00069     struct callable_bad_map<T(U...)> {
00070       typedef undefined_return<T(U...)> result_type;
00071     };
00072   }
00073 
00075   template <typename T>
00076   struct is_callable
00077 #ifndef DOC_GEN
00078     : public is_callable<T()>
00079 #endif
00080   {
00081   };
00082 
00085   template <typename T, typename... U>
00086   struct is_callable<T(U...)>:
00087     public identity<decltype(details::
00088                              is_callable_helper(details::try_first(),
00089                                                 std::declval<T>(),
00090                                                 std::declval<U>()...))>
00091   ::type {
00092     typedef decltype(details::
00093                      is_callable_helper(details::try_first(),
00094                                         std::declval<T>(),
00095                                         std::declval<U>()...))
00096     super;
00097     typedef typename
00098     std::conditional<super::value,
00099                      details::callable_real_map<T(U...)>,
00100                      details::callable_bad_map<T(U...)> >::type::result_type
00101     result_type;
00102   };
00103 
00105   template <typename... U>
00106   struct is_callable<void(U...)>:
00107     public std::false_type {
00108     typedef undefined_return<void(U...)> result_type;
00109   };
00110 }
00111 
00112 #endif