/* Copyright (C) 2013 Tom Bachmann This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #ifndef CXX_TRAITS_H #define CXX_TRAITS_H // only for true_/false_ #include "mp.h" namespace flint { namespace detail { template struct wrap { T t; }; } // detail namespace traits { /////////////////////// // BASIC TYPE TRAITS /////////////////////// // These helpers can be used to manipulate and inquire type information. // For example, given an arbitrary type T, one might be interested in knowing // if it is an integral type (int, short, ulong, etc). // // This file contains generic traits, not specific to FLINT. using mp::true_; using mp::false_; // Compute if T belongs to the signed integer types. template struct is_signed_integer : false_ { }; template<> struct is_signed_integer : true_ { }; template<> struct is_signed_integer : true_ { }; template<> struct is_signed_integer : true_ { }; template<> struct is_signed_integer : true_ { }; // Compute if T belongs to the unsigned integer types. template struct is_unsigned_integer : false_ { }; template<> struct is_unsigned_integer : true_ { }; template<> struct is_unsigned_integer : true_ { }; template<> struct is_unsigned_integer : true_ { }; template<> struct is_unsigned_integer : true_ { }; // Compute if T belongs to the signed or unsigned integer types template struct is_integer : mp::or_, is_signed_integer > { }; // Compute if T can always losslessly be converted into an slong template struct fits_into_slong : mp::false_ { }; template struct fits_into_slong >::type> : mp::or_< is_signed_integer, mp::and_v< is_unsigned_integer, sizeof(T) < sizeof(slong) > > { }; template struct fits_into_flint_bitcnt_t : is_unsigned_integer { }; // Compute if T is like const char* template struct is_string : mp::false_ { }; template<> struct is_string : mp::true_ { }; template<> struct is_string : mp::true_ { }; template struct is_string : mp::true_ { }; template struct is_string : mp::true_ { }; // Compute a type appropriate for forwarding T. This is just the appropriate // constant reference type (but avoids things like const (int&)&, which cause // syntax errors. template struct forwarding {typedef const T& type;}; template struct forwarding {typedef T& type;}; template struct forwarding {typedef const T& type;}; template struct forwarding >::type> { typedef T type; }; template struct forwarding {typedef T* type;}; template<> struct forwarding {typedef bool type;}; // Compute a type appropriate for referencing. Usually T&. template struct reference {typedef T& type;}; template struct reference {typedef T& type;}; template struct reference {typedef const T& type;}; // Add a constant qualification. In particular, turn T& into const T&. template struct make_const {typedef const T type;}; template struct make_const {typedef const T& type;}; // Strip const and reference type annotations. This does *not* strip pointers! template struct basetype {typedef T type;}; template struct basetype {typedef T type;}; template struct basetype {typedef T type;}; template struct basetype {typedef T type;}; struct no { int data[2]; }; typedef int yes; template detail::wrap fakeinstance(); // use with care template struct _is_convertible { private: static yes test(...) {return yes();} static no test(To) {return no();} public: static const bool val = (sizeof(test(fakeinstance().t)) != sizeof(yes)); }; // XXX HACK template struct _is_convertible : false_ { }; } // traits } // flint #endif