mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-03 08:20:28 +00:00
wip ctl type traits
I am a bit ambivalent about this. <type_traits> is actually not that bad by STL standards, “only” 148 transitive includes for the whole file. The split out variants under __type_traits are also mostly reasonable - e.g. __type_traits/is_same.h only includes 4 other STL files. Many others ask for more, but nothing is all that egregious. I do think we can probably provide an 80–95% solution with a fraction of the footprint in CTL by for example eliding direct struct definitions in favor of the _t or _v variants when the latter are simpler to write, and omitting the more obscure tests in favor of a common core. I don’t think it’s worth splitting things out by file but it might be worth it to e.g. have a type_traits.h and a type_traits_advanced.h or something.
This commit is contained in:
parent
9a5a13854d
commit
163d6c102a
2 changed files with 199 additions and 0 deletions
71
ctl/type_traits.cc
Normal file
71
ctl/type_traits.cc
Normal file
|
@ -0,0 +1,71 @@
|
|||
// -*- mode:c++; indent-tabs-mode:nil; c-basic-offset:4; coding:utf-8 -*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
//
|
||||
// Copyright 2024 Justine Alexandra Roberts Tunney
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for
|
||||
// any purpose with or without fee is hereby granted, provided that the
|
||||
// above copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "type_traits.h"
|
||||
|
||||
// #include <type_traits>
|
||||
// #define ctl std
|
||||
|
||||
using namespace ctl;
|
||||
|
||||
#undef ctl
|
||||
|
||||
static_assert(is_void_v<void>);
|
||||
static_assert(is_void_v<const void>);
|
||||
static_assert(is_void_v<volatile const void>);
|
||||
|
||||
static_assert(is_same_v<int, int>);
|
||||
static_assert(!is_same_v<int, bool>);
|
||||
|
||||
struct A
|
||||
{
|
||||
};
|
||||
|
||||
using B = A;
|
||||
|
||||
struct C
|
||||
{
|
||||
};
|
||||
|
||||
struct Base
|
||||
{
|
||||
};
|
||||
|
||||
struct Derived : Base
|
||||
{
|
||||
};
|
||||
|
||||
static_assert(is_same_v<A, A>);
|
||||
static_assert(is_same_v<A, B>);
|
||||
static_assert(!is_same_v<A, C>);
|
||||
static_assert(!is_same_v<Base, Derived>);
|
||||
|
||||
static_assert(is_convertible_v<int, bool>);
|
||||
static_assert(is_convertible_v<Derived, Base>);
|
||||
static_assert(!is_convertible_v<Base, Derived>);
|
||||
static_assert(is_convertible_v<Derived*, Base*>);
|
||||
static_assert(!is_convertible_v<Base*, Derived*>);
|
||||
|
||||
static_assert(is_convertible_v<A&, const A&>);
|
||||
static_assert(is_convertible_v<A&&, const A&>);
|
||||
static_assert(!is_convertible_v<const A&, A&>);
|
||||
static_assert(!is_convertible_v<A&, A&&>);
|
||||
static_assert(!is_convertible_v<A&&, A&>);
|
||||
|
||||
static_assert(is_same_v<int, remove_extent_t<int[]>>);
|
||||
static_assert(is_same_v<int, remove_extent_t<int[5]>>);
|
128
ctl/type_traits.h
Normal file
128
ctl/type_traits.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef COSMOPOLITAN_CTL_TYPE_TRAITS_H_
|
||||
#define COSMOPOLITAN_CTL_TYPE_TRAITS_H_
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template <typename T, T V>
|
||||
struct integral_constant
|
||||
{
|
||||
using value_type = T;
|
||||
using type = integral_constant<T, V>;
|
||||
|
||||
static constexpr T value = V;
|
||||
|
||||
constexpr operator value_type() const noexcept
|
||||
{
|
||||
return V;
|
||||
}
|
||||
|
||||
constexpr value_type operator()() const noexcept
|
||||
{
|
||||
return V;
|
||||
}
|
||||
};
|
||||
|
||||
using true_type = integral_constant<bool, true>;
|
||||
using false_type = integral_constant<bool, false>;
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same : false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_same<T, T> : true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_same_v = is_same<T, U>::value;
|
||||
|
||||
template <typename T>
|
||||
struct remove_extent
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_extent<T[]>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct remove_extent<T[N]>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_extent_t = typename remove_extent<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct remove_cv
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_cv<const T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_cv<volatile T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_cv<const volatile T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_void_v = is_same_v<void, remove_cv_t<T>>;
|
||||
|
||||
namespace __ {
|
||||
|
||||
template <typename T>
|
||||
auto test_returnable(int) -> decltype(
|
||||
void(static_cast<T(*)()>(nullptr)), true_type{});
|
||||
|
||||
template <typename>
|
||||
auto test_returnable(...) -> false_type;
|
||||
|
||||
template <typename T, typename U>
|
||||
auto test_implicitly_convertible(int) -> decltype(
|
||||
void(declval<void(&)(U)>()(declval<T>())), true_type{});
|
||||
|
||||
template <typename, typename>
|
||||
auto test_implicitly_convertible(...) -> false_type;
|
||||
|
||||
} // namespace __
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_convertible : integral_constant<bool,
|
||||
(decltype(__::test_returnable<U>(0))::value &&
|
||||
decltype(__::test_implicitly_convertible<T, U>(0))::value) ||
|
||||
(is_void_v<T> && is_void_v<U>)
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_convertible_v = is_convertible<T, U>::value;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // COSMOPOLITAN_CTL_TYPE_TRAITS_H_
|
Loading…
Add table
Add a link
Reference in a new issue