diff --git a/ctl/optional.h b/ctl/optional.h index 26fa97bad..1e03c10dd 100644 --- a/ctl/optional.h +++ b/ctl/optional.h @@ -3,9 +3,7 @@ #ifndef COSMOPOLITAN_CTL_OPTIONAL_H_ #define COSMOPOLITAN_CTL_OPTIONAL_H_ #include "new.h" -#include <__utility/forward.h> -#include <__utility/move.h> -#include <__utility/swap.h> +#include "utility.h" namespace ctl { @@ -32,7 +30,7 @@ class optional optional(T&& value) : present_(true) { - new (&value_) T(std::move(value)); + new (&value_) T(ctl::move(value)); } optional(const optional& other) : present_(other.present_) @@ -44,7 +42,7 @@ class optional optional(optional&& other) noexcept : present_(other.present_) { if (other.present_) - new (&value_) T(std::move(other.value_)); + new (&value_) T(ctl::move(other.value_)); } optional& operator=(const optional& other) @@ -63,7 +61,7 @@ class optional if (this != &other) { reset(); if (other.present_) - new (&value_) T(std::move(other.value_)); + new (&value_) T(ctl::move(other.value_)); present_ = other.present_; } return *this; @@ -87,7 +85,7 @@ class optional { if (!present_) __builtin_trap(); - return std::move(value_); + return ctl::move(value_); } explicit operator bool() const noexcept @@ -113,19 +111,19 @@ class optional { reset(); present_ = true; - new (&value_) T(std::forward(args)...); + new (&value_) T(ctl::forward(args)...); } void swap(optional& other) noexcept { - using std::swap; + using ctl::swap; if (present_ && other.present_) { swap(value_, other.value_); } else if (present_) { - other.emplace(std::move(value_)); + other.emplace(ctl::move(value_)); reset(); } else if (other.present_) { - emplace(std::move(other.value_)); + emplace(ctl::move(other.value_)); other.reset(); } } diff --git a/ctl/string.h b/ctl/string.h index 0656418a5..42fc14dc3 100644 --- a/ctl/string.h +++ b/ctl/string.h @@ -87,10 +87,7 @@ class string void swap(string& s) noexcept { - char tmp[__::string_size]; - __builtin_memcpy(tmp, blob, __::string_size); - __builtin_memcpy(blob, s.blob, __::string_size); - __builtin_memcpy(s.blob, tmp, __::string_size); + ctl::swap(blob, s.blob); } string(string&& s) noexcept diff --git a/ctl/string_view.h b/ctl/string_view.h index 518c955bd..f4807c62c 100644 --- a/ctl/string_view.h +++ b/ctl/string_view.h @@ -2,6 +2,7 @@ // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi #ifndef COSMOPOLITAN_CTL_STRINGVIEW_H_ #define COSMOPOLITAN_CTL_STRINGVIEW_H_ +#include "utility.h" namespace ctl { diff --git a/ctl/unique_ptr.h b/ctl/unique_ptr.h index 179beda12..6217e2de5 100644 --- a/ctl/unique_ptr.h +++ b/ctl/unique_ptr.h @@ -2,9 +2,7 @@ // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi #ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #define COSMOPOLITAN_CTL_UNIQUE_PTR_H_ -#include <__utility/forward.h> -#include <__utility/move.h> -#include <__utility/swap.h> +#include "utility.h" namespace ctl { @@ -36,11 +34,11 @@ struct unique_ptr } constexpr unique_ptr(pointer p, auto&& d) noexcept - : p(p), d(std::forward(d)) + : p(p), d(ctl::forward(d)) { } - constexpr unique_ptr(unique_ptr&& u) noexcept : p(u.p), d(std::move(u.d)) + constexpr unique_ptr(unique_ptr&& u) noexcept : p(u.p), d(ctl::move(u.d)) { u.p = nullptr; } @@ -89,7 +87,7 @@ struct unique_ptr inline void swap(unique_ptr& r) noexcept { - using std::swap; + using ctl::swap; swap(p, r.p); swap(d, r.d); } @@ -115,7 +113,7 @@ struct unique_ptr } inline element_type& operator*() const - noexcept(noexcept(*std::declval())) + noexcept(noexcept(*ctl::declval())) { if (!p) __builtin_trap(); @@ -134,7 +132,7 @@ template inline unique_ptr make_unique(Args&&... args) { - return unique_ptr(new T(std::forward(args)...)); + return unique_ptr(new T(ctl::forward(args)...)); } template diff --git a/ctl/utility.cc b/ctl/utility.cc new file mode 100644 index 000000000..a4c2a2008 --- /dev/null +++ b/ctl/utility.cc @@ -0,0 +1,19 @@ +// -*- 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 "utility.h" diff --git a/ctl/utility.h b/ctl/utility.h new file mode 100644 index 000000000..62036ca04 --- /dev/null +++ b/ctl/utility.h @@ -0,0 +1,61 @@ +// -*-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_UTILITY_H_ +#define COSMOPOLITAN_CTL_UTILITY_H_ + +namespace ctl { + +namespace __ { + +template +struct no_infer_ +{ + typedef T type; +}; + +template +using no_infer = typename no_infer_::type; + +} // namespace __ + +template +constexpr T&& +move(T& t) noexcept +{ + return static_cast(t); +} + +template +constexpr T&& +forward(__::no_infer& t) noexcept +{ + return static_cast(t); +} + +template +// TODO(mrdomino): requires move_constructible && move_assignable +constexpr void +swap(T& a, T& b) noexcept +{ + T t(ctl::move(a)); + a = ctl::move(b); + b = ctl::move(t); +} + +template +// TODO(mrdomino): requires is_swappable +constexpr void +swap(T (&a)[N], T (&b)[N]) noexcept +{ + for (size_t i = 0; i < N; ++i) { + swap(a[i], b[i]); + } +} + +template +T&& +declval() noexcept; + +} // namespace ctl + +#endif // COSMOPOLITAN_CTL_UTILITY_H_ diff --git a/ctl/vector.h b/ctl/vector.h index 8c9660909..e86e0d503 100644 --- a/ctl/vector.h +++ b/ctl/vector.h @@ -3,9 +3,7 @@ #ifndef COSMOPOLITAN_CTL_OPTIONAL_H_ #define COSMOPOLITAN_CTL_OPTIONAL_H_ #include "new.h" -#include <__utility/forward.h> -#include <__utility/move.h> -#include <__utility/swap.h> +#include "utility.h" namespace ctl { @@ -173,7 +171,7 @@ struct vector return; T* newP = new T[c2]; for (size_t i = 0; i < n; ++i) - newP[i] = std::move(p[i]); + newP[i] = ctl::move(p[i]); delete[] p; p = newP; c = c2; @@ -197,7 +195,7 @@ struct vector c2 += c2 >> 1; reserve(c2); } - new (&p[n]) T(std::forward(e)); + new (&p[n]) T(ctl::forward(e)); ++n; } @@ -209,7 +207,7 @@ struct vector c2 += c2 >> 1; reserve(c2); } - new (&p[n]) T(std::forward(args)...); + new (&p[n]) T(ctl::forward(args)...); ++n; } @@ -236,9 +234,9 @@ struct vector void swap(vector& other) noexcept { - std::swap(n, other.n); - std::swap(c, other.c); - std::swap(p, other.p); + ctl::swap(n, other.n); + ctl::swap(c, other.c); + ctl::swap(p, other.p); } }; diff --git a/libc/integral/cxx.inc b/libc/integral/cxx.inc index 10609b233..5707beeb3 100644 --- a/libc/integral/cxx.inc +++ b/libc/integral/cxx.inc @@ -39,3 +39,5 @@ struct __cxx_choose_expr { /* todo jart whyyyy */ #define _Float16 __fp16 #endif + +using nullptr_t = decltype(nullptr); diff --git a/test/ctl/optional_test.cc b/test/ctl/optional_test.cc index 7d6e231e4..a7d3a9b14 100644 --- a/test/ctl/optional_test.cc +++ b/test/ctl/optional_test.cc @@ -63,7 +63,7 @@ main() { ctl::optional x("world"); - ctl::optional y(std::move(x)); + ctl::optional y(ctl::move(x)); if (!y) return 9; if (!y.has_value()) @@ -87,7 +87,7 @@ main() { ctl::optional x("hello"); ctl::optional y; - y = std::move(x); + y = ctl::move(x); if (!y) return 16; if (!y.has_value()) diff --git a/test/ctl/string_test.cc b/test/ctl/string_test.cc index e43f673a0..22cc0d6e9 100644 --- a/test/ctl/string_test.cc +++ b/test/ctl/string_test.cc @@ -19,7 +19,6 @@ #include "ctl/string.h" #include <__type_traits/is_same.h> -#include <__utility/move.h> #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -211,7 +210,7 @@ main() { String s = "hello"; - String s2 = std::move(s); + String s2 = ctl::move(s); if (s2 != "hello") return 47; if (!s.empty()) diff --git a/test/ctl/string_view_test.cc b/test/ctl/string_view_test.cc index fb43d5898..89da0f3a7 100644 --- a/test/ctl/string_view_test.cc +++ b/test/ctl/string_view_test.cc @@ -18,8 +18,6 @@ #include "ctl/string_view.h" -#include <__utility/move.h> - #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -90,7 +88,7 @@ main(int argc, char* argv[]) { ctl::string_view s = "hello"; - ctl::string_view s2 = std::move(s); + ctl::string_view s2 = ctl::move(s); if (s2 != "hello") return 16; if (s.empty()) diff --git a/test/ctl/unique_ptr_test.cc b/test/ctl/unique_ptr_test.cc index 4d6699b25..77e4b1573 100644 --- a/test/ctl/unique_ptr_test.cc +++ b/test/ctl/unique_ptr_test.cc @@ -18,7 +18,7 @@ #include "ctl/unique_ptr.h" -#include +#include <__type_traits/is_same.h> #include "libc/runtime/runtime.h" @@ -32,7 +32,7 @@ template Ptr Mk(Args&&... args) { - return ctl::make_unique(std::forward(args)...); + return ctl::make_unique(ctl::forward(args)...); } template @@ -161,7 +161,7 @@ main() // shouldn't compile x = y; #endif - x = std::move(y); + x = ctl::move(y); if (g != 1) return 10; if (y) diff --git a/test/ctl/vector_test.cc b/test/ctl/vector_test.cc index 214eef454..bee9c33b0 100644 --- a/test/ctl/vector_test.cc +++ b/test/ctl/vector_test.cc @@ -50,7 +50,7 @@ main() ctl::string yo = "foo"; ctl::vector A; A.push_back("fun"); - A.push_back(std::move(yo)); + A.push_back(ctl::move(yo)); if (yo != "") return 5; A.emplace_back("bar"); @@ -94,7 +94,7 @@ main() A.push_back(1); A.push_back(2); A.push_back(3); - ctl::vector B(std::move(A)); + ctl::vector B(ctl::move(A)); if (A.size() != 0) return 17; if (B.size() != 3) @@ -122,7 +122,7 @@ main() A.push_back(2); A.push_back(3); ctl::vector B; - B = std::move(A); + B = ctl::move(A); if (A.size() != 0) return 22; if (B.size() != 3) @@ -286,7 +286,7 @@ main() A.push_back(2); A.push_back(3); ctl::vector B; - B = std::move(A); + B = ctl::move(A); if (A.size() != 0) return 63; if (B.size() != 3)