// Copyright 2018 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef ASTC_CODEC_BASE_TYPE_TRAITS_H_ #define ASTC_CODEC_BASE_TYPE_TRAITS_H_ #include #include namespace astc_codec { namespace base { namespace details { // a simple helper class for SFINAE below. template struct dummy { using type = X; }; } // namespace details // add some convenience shortcuts for an overly complex std::enable_if syntax // Use 'enable_if' instead of // 'typename std::enable_if::type' template using enable_if = typename std::enable_if::type; // Use 'enable_if_c' instead of // 'typename std::enable_if::type' template using enable_if_c = typename std::enable_if::type; // Use 'enable_if_convertible' instead of // 'typename std::enable_if::value, Type>::type' template using enable_if_convertible = enable_if>; // ----------------------------------------------------------------------------- // A predicate for checking if some object is callable with a specific // signature. Examples: // // is_callable_as::value == false. // is_callable_as::value == false. // is_callable_as::value == true // template struct is_callable_as : std::false_type {}; // This specialization is SFINAE-d out if template arguments can't be combined // into a call expression F(), or if the result of that call is not |R| template struct is_callable_as()( std::declval()...))>::type, R>::value>::type> : std::true_type {}; // // A similar predicate to only check arguments of the function call and ignore // the specified return type // // is_callable_as::value == true // is_callable_as::value == false // is_callable_with_args::value == true // template struct is_callable_with_args : std::false_type {}; template struct is_callable_with_args< F, R(Args...), typename std::enable_if< !std::is_same()(std::declval()...))>::type, F>::value>::type> : std::true_type {}; // ----------------------------------------------------------------------------- // Check if a type |T| is any instantiation of a template |U|. Examples: // // is_template_instantiation_of::value == false // is_template_instantiation_of< // std::list>, std::vector>::value == false // is_template_instantiation_of, std::vector>::value == true // is_template_instantiation_of< // std::vector>, std::vector>::value == true // template class U> struct is_template_instantiation_of : std::false_type {}; template class U, class... Args> struct is_template_instantiation_of, U> : std::true_type {}; // ----------------------------------------------------------------------------- // // is_range - check if type |T| is a range-like type. // // It makes sure that expressions std::begin(t) and std::end(t) are well-formed // and those return the same type. // // Note: with expression SFINAE from C++14 is_range_helper<> could be renamed to // is_range<> with no extra code. C++11 needs an extra level of enable_if<> // to make it work when the type isn't a range. // namespace details { template using is_range_helper = std::is_same< decltype(std::begin( std::declval::type>())), decltype( std::end(std::declval::type>()))>; } // namespace details template struct is_range : std::false_type {}; template struct is_range< T, typename std::enable_if::value>::type> : std::true_type {}; //////////////////////////////////////////////////////////////////////////////// // // A class to incapsulate integer sequence 0, 1, ..., // Seq // Useful to pass function parameters in an array/tuple to call it later. // template struct Seq {}; // A 'maker' class to construct Seq given only // value. // MakeSeq works this way, e.g. // // MakeSeq<2> inherits MakeSeq<2 - 1, 2 - 1> == MakeSeq<1, 1> // MakeSeq<1, 1> : MakeSeq<1 - 1, 1 - 1, 1> == MakeSeq<0, 0, 1> // MakeSeq<0, 0, 1> == MakeSeq<0, S...> and defines |type| = Seq<0, 1> template struct MakeSeq : MakeSeq {}; template struct MakeSeq<0, S...> { using type = Seq; }; // // MakeSeqT alias to quickly create Seq<...>: // MakeSeqT<3> == Seq<0, 1, 2> template using MakeSeqT = typename MakeSeq::type; } // namespace base } // namespace astc_codec #endif // ASTC_CODEC_BASE_TYPE_TRAITS_H_