Stared reimplementing iohelper using concepts

This commit is contained in:
Dreaded_X 2019-12-13 02:05:53 +01:00
commit 62343d06e0
3 changed files with 147 additions and 0 deletions

42
.gitignore vendored Normal file
View File

@ -0,0 +1,42 @@
### Git ###
*.orig
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### premake-gmake ###
Makefile
*.make
build/
### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
# auto-generated tag files
tags
.clangd/
compile_commands.json
### Other stuff ###
.build
bootstrap/build/
bootstrap/vendor/

105
src/write.cpp Normal file
View File

@ -0,0 +1,105 @@
#include <iostream>
#include <cstdint>
namespace io {
template <typename T>
void write(std::ostream&, T) {
static_assert(!std::is_same_v<T,T>, "No known specialization of io::write for type");
}
template <typename T>
concept NumberByte = std::is_integral_v<T> && sizeof(T) == 1;
template <NumberByte T>
void write(std::ostream& os, T value) {
os.write(reinterpret_cast<const char*>(&value), sizeof(T));
}
namespace {
template <typename T>
void write_bytes(std::ostream& os, T value, size_t length) {
for (auto i = length; i > 0; --i) {
uint8_t byte = (value >> (i-1)*8) & 0xFF;
write<uint8_t>(os, byte);
}
}
}
template <typename T> requires std::is_integral_v<T>
void write(std::ostream& os, T value) {
write_bytes(os, value, sizeof(T));
}
// Special implementation for size_t (also uint64_t, so maybe this is not that smart)
template <>
void write(std::ostream& os, size_t value) {
// Check if we need more then one byte
if (value > 0b01111111) {
// Calculate how many bytes we need to store the number
uint8_t length = 0;
auto x = value;
while (x != 0) {
x >>= 8;
length++;
}
write<uint8_t>(os, length | 0b10000000);
write_bytes(os, value, length);
} else {
write<uint8_t>(os, value);
}
}
template <typename T> requires std::is_convertible_v<T, std::string_view>
void write(std::ostream& os, T value) {
std::string_view s = value;
write<size_t>(os, s.length());
os << s;
}
template <typename T>
concept Container = requires (T a) {
typename T::value_type;
typename T::size_type;
typename T::iterator;
typename T::const_iterator;
a.size();
a.begin();
a.end();
a.cbegin();
a.cend();
} && !std::is_convertible_v<T, std::string_view>;
template <Container T>
void write(std::ostream& os, T value) {
write<size_t>(os, value.size());
for (const auto& entry : value) {
write<typename T::value_type>(os, entry);
}
}
}
#include <vector>
#include <array>
struct A {
int b;
};
namespace io {
template <>
void write(std::ostream& os, A value) {
write(os, value.b);
}
}
int main() {
std::cout << "TEST\n";
io::write<size_t>(std::cout, 50);
std::array<char, 2> a = {'a', 'b'};
io::write(std::cout, a);
io::write(std::cout, "test");
io::write(std::cout, A{4});
std::cout << '\n';
}

BIN
test Executable file

Binary file not shown.