core.h

This file contains functions widely used by the core library. It contains functions for object movement, swapping, copying, and hashing, as well as the free function, which deinitializes objects and releases its memory resources.

Memory management

This library does not manage memory, and leaves it to the user to ensure memory is allocated and freed correctly. The core data structures, such as core::array, core::hash_set, core::hash_map, core::array_map do not automatically free their elements upon deallocation. The library uses the core::free() function to free memory resources. When developing a new type, the class/struct should implement the public static function free, as in the example below.

#include <core/core.h>
#include <stdio.h>
#include <string.h>
using namespace core;

struct custom_string {
    char* buffer;

    custom_string() { }

    custom_string(const char* src) {
        buffer = (char*) malloc(sizeof(char) * (strlen(src) + 1));
        memcpy(buffer, src, sizeof(char) * (strlen(src) + 1));
    }

    ~custom_string() {
        core::free(buffer);
    }

    static void free(custom_string& s) {
        core::free(s.buffer);
    }
};

bool init(custom_string& s, const char* src) {
    s.buffer = (char*) malloc(sizeof(char) * (strlen(src) + 1));
    if (s.buffer == NULL)
        return false;
    memcpy(s.buffer, src, sizeof(char) * (strlen(src) + 1));
    return true;
}

int main() {
    custom_string first = custom_string("first");
    custom_string& second = *((custom_string*) alloca(sizeof(custom_string)));
    init(second, "second");

    printf("%s ", first.buffer);
    printf("%s", second.buffer);

    core::free(second);
}
In this example, core::free() is not called on first since it was initialized on the stack, and so its destructor will automatically free buffer. However, this was not the case for second, and so we must call core::free() directly. The expected output of the program is first second.

Classes, functions, and variables in this file
constexpr std::size_tarray_length (const T (&array)[N])
Tmin (const T & first, const T & second)
Tmax (const T & first, const T & second)
boolinit (T & a, const T & b)
voidmove (const T & src, T & dst)
boolcopy (const T & src, T & dst)
voidswap (T & a, T & b)
voidfree (T & a, Args &&... args)
voidfree (T * a)
structis_moveable
structis_swappable
structis_copyable
boolis_empty (const K & key)
voidset_empty (K & key)
template<typename T, std::size_t N>
constexpr std::size_t array_length(
const T(&array)[N])

This function returns the compile-time length of the static array array.

template<typename T>
T min(
const T &first,
const T &second)

Returns first if first < second, and returns second otherwise.

template<typename T>
T max(
const T &first,
const T &second)

Returns second if first < second, and returns first otherwise.

template<typename T>
bool init(
T &a,
const T &b)

If T satisfies is_fundamental, is_enum, or is_pointer, this function assigns a = b.

template<typename T>
void move(
const T &src,
T &dst)

If T satisfies is_fundamental or is_enum, dst is assigned to src. Otherwise, this function calls T::move(src, dst). This function is intended to be used to effectively move the object stored in src into the location specified by dst.

template<typename T>
bool copy(
const T &src,
T &dst)

If T satisfies is_fundamental or is_enum, dst is assigned to src. Otherwise, this function calls and returns the result of T::copy(src, dst). This function is intended to be used to copy the object stored in src into the location specified by dst.

template<typename T>
void swap(
T &a,
T &b)

If T satisfies is_fundamental or is_enum, the values of a and b are swapped. Otherwise, this function calls T::swap(a, b). This function is intended to be used to swap the object stored in a with the object stored in b.

template<typename T, typename... Args>
void free(
T &a,
Args &&...args)

If T satisfies is_fundamental or is_enum, this function does nothing. Otherwise, this function calls T::free(a, std::forward<Args>(args)...). This function is intended to be used to free the object stored in a, passing along any additional arguments. Note that since args is variadic, it may also be empty.

template<typename T>
void free(
T *a)

This function calls std::free on a.

struct is_moveable

template<typename T>

This type trait is true_type if and only if T satisfies any of the following:

  1. is_fundamental,

  2. is_enum,

  3. or implements the public static method void T::move(const T&, T&).

struct is_swappable

template<typename T>

This type trait is true_type if and only if T satisfies any of the following:

  1. is_fundamental,

  2. is_enum,

  3. or implements the public static method void T::swap(T&, T&).

struct is_copyable

template<typename T>

This type trait is true_type if and only if T satisfies any of the following:

  1. is_fundamental,

  2. is_enum,

  3. or implements the public static method bool T::copy(const T&, T&).

template<typename K>
bool is_empty(
const K &key)

Hashtables in this library require the type K to define a special "empty value" to indicate that a bucket is empty. For K that satisfies is_fundamental or is_enum, this function returns whether key == static_cast<K>(0). Otherwise, this function returns K::is_empty(key). Thus, to enable the use of a custom struct/class as a hashtable key, it must implement the public static function is_empty.

template<typename K>
void set_empty(
K &key)

Hashtables in this library require the type K to define a special "empty value" to indicate that a bucket is empty. For K that satisfies is_fundamental or is_enum, this function sets key to static_cast<K>(0). Otherwise, this function calls K::set_empty(key). Some hashtable operations use this operation, and therefore, if a custom struct/class is used as a hashtable key, it must implement the public static function set_empty in order to use the aforementioned hashtable operations.