CTL: utility.h, use ctl::swap in string (#1227)

* Add ctl utility.h

Implements forward, move, swap, and declval. This commit also adds a def
for nullptr_t to cxx.inc. We need it now because the CTL headers stopped
including anything from libc++, so we no longer get their basic types.

* Use ctl::swap in string

The STL spec says that swap is located in the string_view header anyawy.
Performance-wise this is a noop, but it’s slightly cleaner.
This commit is contained in:
Steven Dee (Jōshin) 2024-06-18 22:00:59 -07:00 committed by GitHub
parent a795017416
commit 9a5a13854d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 117 additions and 46 deletions

View file

@ -3,9 +3,7 @@
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_ #ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
#define COSMOPOLITAN_CTL_OPTIONAL_H_ #define COSMOPOLITAN_CTL_OPTIONAL_H_
#include "new.h" #include "new.h"
#include <__utility/forward.h> #include "utility.h"
#include <__utility/move.h>
#include <__utility/swap.h>
namespace ctl { namespace ctl {
@ -32,7 +30,7 @@ class optional
optional(T&& value) : present_(true) optional(T&& value) : present_(true)
{ {
new (&value_) T(std::move(value)); new (&value_) T(ctl::move(value));
} }
optional(const optional& other) : present_(other.present_) optional(const optional& other) : present_(other.present_)
@ -44,7 +42,7 @@ class optional
optional(optional&& other) noexcept : present_(other.present_) optional(optional&& other) noexcept : present_(other.present_)
{ {
if (other.present_) if (other.present_)
new (&value_) T(std::move(other.value_)); new (&value_) T(ctl::move(other.value_));
} }
optional& operator=(const optional& other) optional& operator=(const optional& other)
@ -63,7 +61,7 @@ class optional
if (this != &other) { if (this != &other) {
reset(); reset();
if (other.present_) if (other.present_)
new (&value_) T(std::move(other.value_)); new (&value_) T(ctl::move(other.value_));
present_ = other.present_; present_ = other.present_;
} }
return *this; return *this;
@ -87,7 +85,7 @@ class optional
{ {
if (!present_) if (!present_)
__builtin_trap(); __builtin_trap();
return std::move(value_); return ctl::move(value_);
} }
explicit operator bool() const noexcept explicit operator bool() const noexcept
@ -113,19 +111,19 @@ class optional
{ {
reset(); reset();
present_ = true; present_ = true;
new (&value_) T(std::forward<Args>(args)...); new (&value_) T(ctl::forward<Args>(args)...);
} }
void swap(optional& other) noexcept void swap(optional& other) noexcept
{ {
using std::swap; using ctl::swap;
if (present_ && other.present_) { if (present_ && other.present_) {
swap(value_, other.value_); swap(value_, other.value_);
} else if (present_) { } else if (present_) {
other.emplace(std::move(value_)); other.emplace(ctl::move(value_));
reset(); reset();
} else if (other.present_) { } else if (other.present_) {
emplace(std::move(other.value_)); emplace(ctl::move(other.value_));
other.reset(); other.reset();
} }
} }

View file

@ -87,10 +87,7 @@ class string
void swap(string& s) noexcept void swap(string& s) noexcept
{ {
char tmp[__::string_size]; ctl::swap(blob, s.blob);
__builtin_memcpy(tmp, blob, __::string_size);
__builtin_memcpy(blob, s.blob, __::string_size);
__builtin_memcpy(s.blob, tmp, __::string_size);
} }
string(string&& s) noexcept string(string&& s) noexcept

View file

@ -2,6 +2,7 @@
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_STRINGVIEW_H_ #ifndef COSMOPOLITAN_CTL_STRINGVIEW_H_
#define COSMOPOLITAN_CTL_STRINGVIEW_H_ #define COSMOPOLITAN_CTL_STRINGVIEW_H_
#include "utility.h"
namespace ctl { namespace ctl {

View file

@ -2,9 +2,7 @@
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
#ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_
#define COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #define COSMOPOLITAN_CTL_UNIQUE_PTR_H_
#include <__utility/forward.h> #include "utility.h"
#include <__utility/move.h>
#include <__utility/swap.h>
namespace ctl { namespace ctl {
@ -36,11 +34,11 @@ struct unique_ptr
} }
constexpr unique_ptr(pointer p, auto&& d) noexcept constexpr unique_ptr(pointer p, auto&& d) noexcept
: p(p), d(std::forward<decltype(d)>(d)) : p(p), d(ctl::forward<decltype(d)>(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; u.p = nullptr;
} }
@ -89,7 +87,7 @@ struct unique_ptr
inline void swap(unique_ptr& r) noexcept inline void swap(unique_ptr& r) noexcept
{ {
using std::swap; using ctl::swap;
swap(p, r.p); swap(p, r.p);
swap(d, r.d); swap(d, r.d);
} }
@ -115,7 +113,7 @@ struct unique_ptr
} }
inline element_type& operator*() const inline element_type& operator*() const
noexcept(noexcept(*std::declval<pointer>())) noexcept(noexcept(*ctl::declval<pointer>()))
{ {
if (!p) if (!p)
__builtin_trap(); __builtin_trap();
@ -134,7 +132,7 @@ template<typename T, typename... Args>
inline unique_ptr<T> inline unique_ptr<T>
make_unique(Args&&... args) make_unique(Args&&... args)
{ {
return unique_ptr<T>(new T(std::forward<Args>(args)...)); return unique_ptr<T>(new T(ctl::forward<Args>(args)...));
} }
template<typename T> template<typename T>

19
ctl/utility.cc Normal file
View file

@ -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"

61
ctl/utility.h Normal file
View file

@ -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<typename T>
struct no_infer_
{
typedef T type;
};
template<typename T>
using no_infer = typename no_infer_<T>::type;
} // namespace __
template<typename T>
constexpr T&&
move(T& t) noexcept
{
return static_cast<T&&>(t);
}
template<typename T>
constexpr T&&
forward(__::no_infer<T>& t) noexcept
{
return static_cast<T&&>(t);
}
template<typename T>
// TODO(mrdomino): requires move_constructible<T> && move_assignable<T>
constexpr void
swap(T& a, T& b) noexcept
{
T t(ctl::move(a));
a = ctl::move(b);
b = ctl::move(t);
}
template<typename T, size_t N>
// 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<typename T>
T&&
declval() noexcept;
} // namespace ctl
#endif // COSMOPOLITAN_CTL_UTILITY_H_

View file

@ -3,9 +3,7 @@
#ifndef COSMOPOLITAN_CTL_OPTIONAL_H_ #ifndef COSMOPOLITAN_CTL_OPTIONAL_H_
#define COSMOPOLITAN_CTL_OPTIONAL_H_ #define COSMOPOLITAN_CTL_OPTIONAL_H_
#include "new.h" #include "new.h"
#include <__utility/forward.h> #include "utility.h"
#include <__utility/move.h>
#include <__utility/swap.h>
namespace ctl { namespace ctl {
@ -173,7 +171,7 @@ struct vector
return; return;
T* newP = new T[c2]; T* newP = new T[c2];
for (size_t i = 0; i < n; ++i) for (size_t i = 0; i < n; ++i)
newP[i] = std::move(p[i]); newP[i] = ctl::move(p[i]);
delete[] p; delete[] p;
p = newP; p = newP;
c = c2; c = c2;
@ -197,7 +195,7 @@ struct vector
c2 += c2 >> 1; c2 += c2 >> 1;
reserve(c2); reserve(c2);
} }
new (&p[n]) T(std::forward<T>(e)); new (&p[n]) T(ctl::forward<T>(e));
++n; ++n;
} }
@ -209,7 +207,7 @@ struct vector
c2 += c2 >> 1; c2 += c2 >> 1;
reserve(c2); reserve(c2);
} }
new (&p[n]) T(std::forward<Args>(args)...); new (&p[n]) T(ctl::forward<Args>(args)...);
++n; ++n;
} }
@ -236,9 +234,9 @@ struct vector
void swap(vector& other) noexcept void swap(vector& other) noexcept
{ {
std::swap(n, other.n); ctl::swap(n, other.n);
std::swap(c, other.c); ctl::swap(c, other.c);
std::swap(p, other.p); ctl::swap(p, other.p);
} }
}; };

View file

@ -39,3 +39,5 @@ struct __cxx_choose_expr<false, _T, _U> {
/* todo jart whyyyy */ /* todo jart whyyyy */
#define _Float16 __fp16 #define _Float16 __fp16
#endif #endif
using nullptr_t = decltype(nullptr);

View file

@ -63,7 +63,7 @@ main()
{ {
ctl::optional<ctl::string> x("world"); ctl::optional<ctl::string> x("world");
ctl::optional<ctl::string> y(std::move(x)); ctl::optional<ctl::string> y(ctl::move(x));
if (!y) if (!y)
return 9; return 9;
if (!y.has_value()) if (!y.has_value())
@ -87,7 +87,7 @@ main()
{ {
ctl::optional<ctl::string> x("hello"); ctl::optional<ctl::string> x("hello");
ctl::optional<ctl::string> y; ctl::optional<ctl::string> y;
y = std::move(x); y = ctl::move(x);
if (!y) if (!y)
return 16; return 16;
if (!y.has_value()) if (!y.has_value())

View file

@ -19,7 +19,6 @@
#include "ctl/string.h" #include "ctl/string.h"
#include <__type_traits/is_same.h> #include <__type_traits/is_same.h>
#include <__utility/move.h>
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -211,7 +210,7 @@ main()
{ {
String s = "hello"; String s = "hello";
String s2 = std::move(s); String s2 = ctl::move(s);
if (s2 != "hello") if (s2 != "hello")
return 47; return 47;
if (!s.empty()) if (!s.empty())

View file

@ -18,8 +18,6 @@
#include "ctl/string_view.h" #include "ctl/string_view.h"
#include <__utility/move.h>
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -90,7 +88,7 @@ main(int argc, char* argv[])
{ {
ctl::string_view s = "hello"; ctl::string_view s = "hello";
ctl::string_view s2 = std::move(s); ctl::string_view s2 = ctl::move(s);
if (s2 != "hello") if (s2 != "hello")
return 16; return 16;
if (s.empty()) if (s.empty())

View file

@ -18,7 +18,7 @@
#include "ctl/unique_ptr.h" #include "ctl/unique_ptr.h"
#include <type_traits> #include <__type_traits/is_same.h>
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -32,7 +32,7 @@ template<typename T, typename... Args>
Ptr<T> Ptr<T>
Mk(Args&&... args) Mk(Args&&... args)
{ {
return ctl::make_unique<T, Args...>(std::forward<Args>(args)...); return ctl::make_unique<T, Args...>(ctl::forward<Args>(args)...);
} }
template<typename T> template<typename T>
@ -161,7 +161,7 @@ main()
// shouldn't compile // shouldn't compile
x = y; x = y;
#endif #endif
x = std::move(y); x = ctl::move(y);
if (g != 1) if (g != 1)
return 10; return 10;
if (y) if (y)

View file

@ -50,7 +50,7 @@ main()
ctl::string yo = "foo"; ctl::string yo = "foo";
ctl::vector<ctl::string> A; ctl::vector<ctl::string> A;
A.push_back("fun"); A.push_back("fun");
A.push_back(std::move(yo)); A.push_back(ctl::move(yo));
if (yo != "") if (yo != "")
return 5; return 5;
A.emplace_back("bar"); A.emplace_back("bar");
@ -94,7 +94,7 @@ main()
A.push_back(1); A.push_back(1);
A.push_back(2); A.push_back(2);
A.push_back(3); A.push_back(3);
ctl::vector<int> B(std::move(A)); ctl::vector<int> B(ctl::move(A));
if (A.size() != 0) if (A.size() != 0)
return 17; return 17;
if (B.size() != 3) if (B.size() != 3)
@ -122,7 +122,7 @@ main()
A.push_back(2); A.push_back(2);
A.push_back(3); A.push_back(3);
ctl::vector<int> B; ctl::vector<int> B;
B = std::move(A); B = ctl::move(A);
if (A.size() != 0) if (A.size() != 0)
return 22; return 22;
if (B.size() != 3) if (B.size() != 3)
@ -286,7 +286,7 @@ main()
A.push_back(2); A.push_back(2);
A.push_back(3); A.push_back(3);
ctl::vector<int> B; ctl::vector<int> B;
B = std::move(A); B = ctl::move(A);
if (A.size() != 0) if (A.size() != 0)
return 63; return 63;
if (B.size() != 3) if (B.size() != 3)