diff --git a/.gitignore b/.gitignore
index b0b96e5af..f62e363dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,4 +43,6 @@ lokinet.exe
rapidjson/
-.gradle/
\ No newline at end of file
+.gradle/
+.idea
+.vscode
diff --git a/.idea/artifacts/loki_network.xml b/.idea/artifacts/loki_network.xml
deleted file mode 100644
index bc864a9a5..000000000
--- a/.idea/artifacts/loki_network.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
- $PROJECT_DIR$/android/build/artifacts/loki_network
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 30aa626c2..000000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/loki-network.iml b/.idea/loki-network.iml
deleted file mode 100644
index e28944b24..000000000
--- a/.idea/loki-network.iml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 9db281056..000000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 3f4ab2c12..000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1ddfb..000000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
deleted file mode 100644
index 91a7b8a31..000000000
--- a/.idea/workspace.xml
+++ /dev/null
@@ -1,560 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1541522484586
-
-
- 1541522484586
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- loki-network
-
-
-
-
-
-
-
-
-
-
-
-
- Android
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1.8
-
-
-
-
-
-
-
-
-
-
-
- loki-network
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
deleted file mode 100644
index 8c9f05481..000000000
--- a/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "configurations": [
- {
- "name": "Linux",
- "browse": {
- "path": [
- "${workspaceFolder}/llarp",
- "${workspaceFolder}/daemon",
- "${workspaceFolder}/include",
- "${workspaceFolder}/libabyss/src",
- "${workspaceFolder}/crypto",
- "${workspaceFolder}/vendor/cppbackport-master/lib"
- ],
- "limitSymbolsToIncludedHeaders": true
- },
- "includePath": [
- "${workspaceFolder}/include",
- "${workspaceFolder}/llarp",
- "${workspaceFolder}/vendor/cppbackport-master/lib",
- "${workspaceFolder}/libabyss/include",
- "${workspaceFolder}/crypto/include"
- ],
- "defines": [],
- "compilerPath": "/usr/bin/clang",
- "cStandard": "c11",
- "cppStandard": "c++17",
- "intelliSenseMode": "clang-x64"
- }
- ],
- "version": 4
-}
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index e1eabfa58..000000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- // Use IntelliSense to learn about possible attributes.
- // Hover to view descriptions of existing attributes.
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
- "version": "0.2.0",
- "configurations": [{
- "name": "(lldb) Launch",
- "type": "cppdbg",
- "request": "launch",
- "program": "${workspaceFolder}/build/testAll",
- "args": ["--gtest_shuffle", "--gtest_filter=TestThreadPool*"],
- "stopAtEntry": false,
- "cwd": "${workspaceFolder}",
- "environment": [],
- "externalConsole": false,
- "MIMode": "lldb"
- },
- {
- "name": "(gdb) Launch",
- "type": "cppdbg",
- "request": "launch",
- "program": "${workspaceFolder}/lokinet",
- "args": [],
- "stopAtEntry": false,
- "cwd": "${workspaceFolder}",
- "environment": [],
- "externalConsole": true,
- "MIMode": "gdb",
- "setupCommands": [{
- "description": "Enable pretty-printing for gdb",
- "text": "-enable-pretty-printing",
- "ignoreFailures": true
- }]
- }
- ]
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 146ac739a..000000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,76 +0,0 @@
-{
- "editor.formatOnSave": true,
- "files.associations": {
- "array": "cpp",
- "limits": "cpp",
- "cctype": "cpp",
- "clocale": "cpp",
- "cmath": "cpp",
- "cstdarg": "cpp",
- "cstddef": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "cwctype": "cpp",
- "atomic": "cpp",
- "*.tcc": "cpp",
- "bitset": "cpp",
- "chrono": "cpp",
- "codecvt": "cpp",
- "condition_variable": "cpp",
- "cstdint": "cpp",
- "deque": "cpp",
- "list": "cpp",
- "unordered_map": "cpp",
- "unordered_set": "cpp",
- "exception": "cpp",
- "filesystem": "cpp",
- "string_view": "cpp",
- "fstream": "cpp",
- "functional": "cpp",
- "initializer_list": "cpp",
- "iomanip": "cpp",
- "iosfwd": "cpp",
- "iostream": "cpp",
- "istream": "cpp",
- "memory": "cpp",
- "mutex": "cpp",
- "optional": "cpp",
- "ostream": "cpp",
- "ratio": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "streambuf": "cpp",
- "system_error": "cpp",
- "thread": "cpp",
- "cinttypes": "cpp",
- "type_traits": "cpp",
- "tuple": "cpp",
- "typeindex": "cpp",
- "typeinfo": "cpp",
- "utility": "cpp",
- "__config": "cpp",
- "__nullptr": "cpp",
- "algorithm": "cpp",
- "io": "cpp",
- "strstream": "cpp",
- "numeric": "cpp",
- "valarray": "cpp",
- "*.ipp": "cpp",
- "csignal": "cpp",
- "future": "cpp",
- "map": "cpp",
- "vector": "cpp",
- "new": "cpp",
- "shared_mutex": "cpp",
- "complex": "cpp",
- "variant": "cpp",
- "any": "cpp",
- "tuntap.h": "c",
- "hashtable": "cpp",
- "__mutex_base": "cpp",
- "iterator": "cpp"
- }
-}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
deleted file mode 100644
index 6f34e0472..000000000
--- a/.vscode/tasks.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- // See https://go.microsoft.com/fwlink/?LinkId=733558
- // for the documentation about the tasks.json format
- "version": "2.0.0",
- "tasks": [
- {
- "label": "build",
- "type": "shell",
- "command": "make -j8 JSONRPC=ON test",
- "group": "build",
- "problemMatcher": [
- "$gcc"
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 40c139d7f..305f48d94 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,8 +45,12 @@ add_compile_options(-Wno-cast-function-type)
set(FS_LIB stdc++fs)
endif(WIN32)
+
+
if(DEBIAN)
add_definitions(-DDEBIAN)
+else()
+ set(CRYPTO_FLAGS -march=native)
endif()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
@@ -112,18 +116,6 @@ if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
add_compile_options( ${DEBUG_FLAGS} )
endif()
-if(NOT DEBIAN)
-if(NOT ANDROID)
-if (NOT USE_AVX2)
-set(CRYPTO_FLAGS -march=core2 -mtune=native)
-set(CMAKE_ASM_FLAGS "-march=core2")
-else()
-set(CRYPTO_FLAGS -march=haswell -mtune=native)
-set(CMAKE_ASM_FLAGS "-march=haswell -mtune=native ${CMAKE_ASM_FLAGS} $ENV{ASFLAGS}")
-endif()
-endif()
-endif()
-
if(RPI)
add_definitions(-DRPI)
set(WITH_STATIC ON)
diff --git a/Makefile b/Makefile
index d6b29087c..6f6b8a78f 100644
--- a/Makefile
+++ b/Makefile
@@ -52,12 +52,13 @@ RPI ?= OFF
STATIC_LINK ?= OFF
NETNS ?= OFF
CLANG ?= OFF
+CROSS ?= OFF
CMAKE_GEN ?= Unix Makefiles
BUILD_ROOT = $(REPO)/build
-CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DUSING_CLANG=$(CLANG) -DSTATIC_LINK=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DUSE_LIBABYSS=$(JSONRPC) -DRPI=$(RPI) '$(REPO)'")
+CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DUSING_CLANG=$(CLANG) -DSTATIC_LINK=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DUSE_LIBABYSS=$(JSONRPC) -DRPI=$(RPI) '$(REPO)'")
SCAN_BUILD ?= scan-build
ANALYZE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "$(SCAN_BUILD) cmake -DUSE_LIBABYSS=$(JSONRPC) '$(REPO)'")
diff --git a/docker/ubuntu.Dockerfile b/docker/ubuntu.Dockerfile
new file mode 100644
index 000000000..67e511fd0
--- /dev/null
+++ b/docker/ubuntu.Dockerfile
@@ -0,0 +1,10 @@
+FROM ubuntu:latest
+
+RUN apt update && \
+ apt install -y build-essential cmake git libcap-dev wget rapidjson-dev
+
+WORKDIR /src/
+
+COPY . /src/
+
+RUN make -j 8 JSONRPC=ON
diff --git a/include/llarp/crypto.hpp b/include/llarp/crypto.hpp
index 0ec8cbfec..c7a25a812 100644
--- a/include/llarp/crypto.hpp
+++ b/include/llarp/crypto.hpp
@@ -17,19 +17,19 @@ namespace llarp
const byte_t*
pq_keypair_to_secret(const byte_t* keypair);
- typedef AlignedBuffer< SHAREDKEYSIZE > SharedSecret;
- typedef AlignedBuffer< 32 > KeyExchangeNonce;
- typedef AlignedBuffer< PUBKEYSIZE > PubKey;
- typedef AlignedBuffer< SECKEYSIZE > SecretKey;
- typedef AlignedBuffer< SHORTHASHSIZE > ShortHash;
- typedef AlignedBuffer< SIGSIZE > Signature;
- typedef AlignedBuffer< TUNNONCESIZE > TunnelNonce;
- typedef AlignedBuffer< NONCESIZE > SymmNonce;
- typedef AlignedBuffer< 32 > SymmKey;
-
- typedef AlignedBuffer< PQ_CIPHERTEXTSIZE + 1 > PQCipherBlock;
- typedef AlignedBuffer< PQ_PUBKEYSIZE > PQPubKey;
- typedef AlignedBuffer< PQ_KEYPAIRSIZE > PQKeyPair;
+ using SharedSecret = AlignedBuffer< SHAREDKEYSIZE >;
+ using KeyExchangeNonce = AlignedBuffer< 32 >;
+ using PubKey = AlignedBuffer< PUBKEYSIZE >;
+ using SecretKey = AlignedBuffer< SECKEYSIZE >;
+ using ShortHash = AlignedBuffer< SHORTHASHSIZE >;
+ using Signature = AlignedBuffer< SIGSIZE >;
+ using TunnelNonce = AlignedBuffer< TUNNONCESIZE >;
+ using SymmNonce = AlignedBuffer< NONCESIZE >;
+ using SymmKey = AlignedBuffer< 32 >;
+
+ using PQCipherBlock = AlignedBuffer< PQ_CIPHERTEXTSIZE + 1 >;
+ using PQPubKey = AlignedBuffer< PQ_PUBKEYSIZE >;
+ using PQKeyPair = AlignedBuffer< PQ_KEYPAIRSIZE >;
} // namespace llarp
diff --git a/include/llarp/dht/bucket.hpp b/include/llarp/dht/bucket.hpp
index 276b7173e..5ac3ffacb 100644
--- a/include/llarp/dht/bucket.hpp
+++ b/include/llarp/dht/bucket.hpp
@@ -14,7 +14,7 @@ namespace llarp
template < typename Val_t >
struct Bucket
{
- typedef std::map< Key_t, Val_t, XorMetric > BucketStorage_t;
+ using BucketStorage_t = std::map< Key_t, Val_t, XorMetric >;
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
diff --git a/include/llarp/dht/context.hpp b/include/llarp/dht/context.hpp
index acdfeba8a..066b9ba75 100644
--- a/include/llarp/dht/context.hpp
+++ b/include/llarp/dht/context.hpp
@@ -74,7 +74,7 @@ namespace llarp
Validate(const V& value) const = 0;
void
- OnFound(const Key_t& askedPeer, const V& value)
+ OnFound(const Key_t askedPeer, const V& value)
{
peersAsked.insert(askedPeer);
if(Validate(value))
@@ -98,18 +98,26 @@ namespace llarp
Key_t peer;
if(next)
{
- peer = *next.get();
+ // explicit next peer provided
+ peer = next->data();
}
- else
+ else if(!GetNextPeer(peer, peersAsked))
{
- if(!GetNextPeer(peer, peersAsked))
- {
- // no more peers
- SendReply();
- return false;
- }
+ // no more peers
+ llarp::LogInfo("no more peers for request asking for", target);
+ return false;
}
+ const Key_t targetKey = target.data();
+ if((prevPeer ^ targetKey) < (peer ^ targetKey))
+ {
+ // next peer is not closer
+ llarp::LogInfo("next peer ", peer, " is not closer to ", target,
+ " than ", prevPeer);
+ return false;
+ }
+ else
+ peersAsked.insert(peer);
DoNextRequest(peer);
return true;
}
@@ -118,11 +126,11 @@ namespace llarp
SendReply() = 0;
};
- typedef std::function< void(const std::vector< service::IntroSet >&) >
- IntroSetLookupHandler;
+ using IntroSetLookupHandler =
+ std::function< void(const std::vector< service::IntroSet >&) >;
- typedef std::function< void(const std::vector< RouterContact >&) >
- RouterLookupHandler;
+ using RouterLookupHandler =
+ std::function< void(const std::vector< RouterContact >&) >;
struct Context
{
@@ -297,6 +305,7 @@ namespace llarp
{
(void)whoasked;
tx.emplace(askpeer, std::unique_ptr< TX< K, V > >(t));
+ auto count = waiting.count(k);
waiting.insert(std::make_pair(k, askpeer));
auto itr = timeouts.find(k);
@@ -305,7 +314,8 @@ namespace llarp
timeouts.insert(
std::make_pair(k, time_now_ms() + requestTimeoutMS));
}
- t->Start(askpeer);
+ if(count == 0)
+ t->Start(askpeer);
}
/// mark tx as not fond
@@ -316,12 +326,11 @@ namespace llarp
auto txitr = tx.find(from);
if(txitr == tx.end())
return;
- if(next)
- {
- // ask for next peer
- if(txitr->second->AskNextPeer(from.node, next))
- sendReply = false;
- }
+
+ // ask for next peer
+ if(txitr->second->AskNextPeer(from.node, next))
+ sendReply = false;
+
llarp::LogWarn("Target key ", txitr->second->target);
Inform(from, txitr->second->target, {}, sendReply, sendReply);
}
diff --git a/include/llarp/dns_dotlokilookup.hpp b/include/llarp/dns_dotlokilookup.hpp
index d864b38f5..f5062a419 100644
--- a/include/llarp/dns_dotlokilookup.hpp
+++ b/include/llarp/dns_dotlokilookup.hpp
@@ -9,8 +9,8 @@
#include "dnsd.hpp"
-typedef bool (*map_address_hook_func)(const llarp::service::Address &addr,
- uint32_t ip);
+using map_address_hook_func =
+ std::function< bool(const llarp::service::Address &addr, uint32_t ip) >;
/// dotLokiLookup context/config
struct dotLokiLookup
diff --git a/include/llarp/dnsd.hpp b/include/llarp/dnsd.hpp
index 6a7f6b58b..5bac27ae1 100644
--- a/include/llarp/dnsd.hpp
+++ b/include/llarp/dnsd.hpp
@@ -14,8 +14,9 @@
struct dnsd_context;
/// sendto hook functor
-typedef ssize_t (*sendto_dns_hook_func)(void *sock, const struct sockaddr *from,
- const void *buffer, size_t length);
+using sendto_dns_hook_func =
+ std::function< ssize_t(void *sock, const struct sockaddr *from,
+ const void *buffer, size_t length) >;
// FIXME: llarp::Addr
/// DNS server query request
@@ -89,9 +90,9 @@ writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from,
//
/// intercept query hook functor
-typedef dnsd_query_hook_response *(*intercept_query_hook)(
+using intercept_query_hook = std::function< dnsd_query_hook_response *(
std::string name, const struct sockaddr *from,
- struct dnsd_question_request *request);
+ struct dnsd_question_request *request) >;
// FIXME: llarp::Addr
/// DNS Server context
diff --git a/include/llarp/encrypted_frame.hpp b/include/llarp/encrypted_frame.hpp
index 73c7821ad..6cb2c73cb 100644
--- a/include/llarp/encrypted_frame.hpp
+++ b/include/llarp/encrypted_frame.hpp
@@ -50,7 +50,7 @@ namespace llarp
template < typename User >
struct AsyncFrameEncrypter
{
- typedef void (*EncryptHandler)(EncryptedFrame*, User*);
+ using EncryptHandler = std::function< void(EncryptedFrame*, User*) >;
static void
Encrypt(void* user)
@@ -96,7 +96,7 @@ namespace llarp
template < typename User >
struct AsyncFrameDecrypter
{
- typedef void (*DecryptHandler)(llarp_buffer_t*, User*);
+ using DecryptHandler = std::function< void(llarp_buffer_t*, User*) >;
static void
Decrypt(void* user)
diff --git a/include/llarp/exit_info.hpp b/include/llarp/exit_info.hpp
index 4b7d1b90d..1c564596b 100644
--- a/include/llarp/exit_info.hpp
+++ b/include/llarp/exit_info.hpp
@@ -64,7 +64,7 @@ namespace llarp
return out;
out << std::string("/");
#if defined(ANDROID) || defined(RPI)
- snprintf(tmp, sizeof(tmp), "%lu",
+ snprintf(tmp, sizeof(tmp), "%zu",
llarp::bits::count_array_bits(xi.netmask.s6_addr));
return out << tmp;
#else
diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp
index c5a3bbe8f..d1b33c0b9 100644
--- a/include/llarp/handlers/tun.hpp
+++ b/include/llarp/handlers/tun.hpp
@@ -119,10 +119,9 @@ namespace llarp
ObtainIPForAddr(const byte_t* addr);
protected:
- typedef llarp::util::CoDelQueue<
+ using PacketQueue_t = llarp::util::CoDelQueue<
net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime,
- net::IPv4Packet::CompareOrder, net::IPv4Packet::GetNow >
- PacketQueue_t;
+ net::IPv4Packet::CompareOrder, net::IPv4Packet::GetNow >;
/// queue for sending packets over the network from us
PacketQueue_t m_UserToNetworkPktQueue;
/// queue for sending packets to user from network
diff --git a/include/llarp/link/server.hpp b/include/llarp/link/server.hpp
index a7e348999..0c622ed42 100644
--- a/include/llarp/link/server.hpp
+++ b/include/llarp/link/server.hpp
@@ -133,8 +133,8 @@ namespace llarp
uint32_t tick_id;
protected:
- typedef util::NullLock Lock;
- typedef util::NullMutex Mutex;
+ using Lock = util::NullLock;
+ using Mutex = util::NullMutex;
void
PutSession(ILinkSession* s);
diff --git a/include/llarp/link_message.hpp b/include/llarp/link_message.hpp
index c8e4b3216..d2222e787 100644
--- a/include/llarp/link_message.hpp
+++ b/include/llarp/link_message.hpp
@@ -14,7 +14,7 @@ namespace llarp
{
struct ILinkSession;
- typedef std::queue< ILinkMessage* > SendQueue;
+ using SendQueue = std::queue< ILinkMessage* >;
/// parsed link layer message
struct ILinkMessage : public IBEncodeMessage
diff --git a/include/llarp/nodedb.hpp b/include/llarp/nodedb.hpp
index 2d4e88288..eee7b3e6c 100644
--- a/include/llarp/nodedb.hpp
+++ b/include/llarp/nodedb.hpp
@@ -83,7 +83,8 @@ llarp_nodedb_del_rc(struct llarp_nodedb *n, const llarp::RouterID &pk);
/// struct for async rc verification
struct llarp_async_verify_rc;
-typedef void (*llarp_async_verify_rc_hook_func)(struct llarp_async_verify_rc *);
+using llarp_async_verify_rc_hook_func =
+ std::function< void(struct llarp_async_verify_rc *) >;
/// verify rc request
struct llarp_async_verify_rc
@@ -118,7 +119,8 @@ llarp_nodedb_async_verify(struct llarp_async_verify_rc *job);
struct llarp_async_load_rc;
-typedef void (*llarp_async_load_rc_hook_func)(struct llarp_async_load_rc *);
+using llarp_async_load_rc_hook_func =
+ std::function< void(struct llarp_async_load_rc *) >;
struct llarp_async_load_rc
{
diff --git a/include/llarp/path.hpp b/include/llarp/path.hpp
index a28aa699e..f357ac161 100644
--- a/include/llarp/path.hpp
+++ b/include/llarp/path.hpp
@@ -280,19 +280,19 @@ namespace llarp
/// A path we made
struct Path : public IHopHandler, public llarp::routing::IMessageHandler
{
- typedef std::function< void(Path*) > BuildResultHookFunc;
- typedef std::function< bool(Path*, llarp_time_t) > CheckForDeadFunc;
- typedef std::function< bool(Path*, const PathID_t&, uint64_t) >
- DropHandlerFunc;
- typedef std::vector< PathHopConfig > HopList;
- typedef std::function< bool(Path*, const service::ProtocolFrame*) >
- DataHandlerFunc;
- typedef std::function< bool(Path*) > ExitUpdatedFunc;
- typedef std::function< bool(Path*) > ExitClosedFunc;
- typedef std::function< bool(Path*, llarp_buffer_t) >
- ExitTrafficHandlerFunc;
+ using BuildResultHookFunc = std::function< void(Path*) >;
+ using CheckForDeadFunc = std::function< bool(Path*, llarp_time_t) >;
+ using DropHandlerFunc =
+ std::function< bool(Path*, const PathID_t&, uint64_t) >;
+ using HopList = std::vector< PathHopConfig >;
+ using DataHandlerFunc =
+ std::function< bool(Path*, const service::ProtocolFrame*) >;
+ using ExitUpdatedFunc = std::function< bool(Path*) >;
+ using ExitClosedFunc = std::function< bool(Path*) >;
+ using ExitTrafficHandlerFunc =
+ std::function< bool(Path*, llarp_buffer_t) >;
/// (path, backoff) backoff is 0 on success
- typedef std::function< bool(Path*, llarp_time_t) > ObtainedExitHandler;
+ using ObtainedExitHandler = std::function< bool(Path*, llarp_time_t) >;
HopList hops;
@@ -612,15 +612,15 @@ namespace llarp
void
RemovePathSet(PathSet* set);
- typedef std::multimap< PathID_t, std::shared_ptr< TransitHop > >
- TransitHopsMap_t;
+ using TransitHopsMap_t =
+ std::multimap< PathID_t, std::shared_ptr< TransitHop > >;
- typedef std::pair< util::Mutex, TransitHopsMap_t > SyncTransitMap_t;
+ using SyncTransitMap_t = std::pair< util::Mutex, TransitHopsMap_t >;
// maps path id -> pathset owner of path
- typedef std::map< PathID_t, PathSet* > OwnedPathsMap_t;
+ using OwnedPathsMap_t = std::map< PathID_t, PathSet* >;
- typedef std::pair< util::Mutex, OwnedPathsMap_t > SyncOwnedPathsMap_t;
+ using SyncOwnedPathsMap_t = std::pair< util::Mutex, OwnedPathsMap_t >;
llarp_threadpool*
Worker();
diff --git a/include/llarp/path_types.hpp b/include/llarp/path_types.hpp
index 77b0fee1a..20830e79f 100644
--- a/include/llarp/path_types.hpp
+++ b/include/llarp/path_types.hpp
@@ -6,7 +6,7 @@
namespace llarp
{
- typedef AlignedBuffer< PATHIDSIZE > PathID_t;
+ using PathID_t = AlignedBuffer< PATHIDSIZE >;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/include/llarp/pathset.hpp b/include/llarp/pathset.hpp
index 07d25bef9..055e964b4 100644
--- a/include/llarp/pathset.hpp
+++ b/include/llarp/pathset.hpp
@@ -60,6 +60,10 @@ namespace llarp
void
Tick(llarp_time_t now, llarp_router* r);
+ /// count the number of paths that will exist at this timestamp in future
+ size_t
+ NumPathsExistingAt(llarp_time_t futureTime) const;
+
void
RemovePath(Path* path);
@@ -176,7 +180,7 @@ namespace llarp
size_t m_NumPaths;
private:
- typedef std::pair< RouterID, PathID_t > PathInfo_t;
+ using PathInfo_t = std::pair< RouterID, PathID_t >;
struct PathInfoHash
{
@@ -187,7 +191,7 @@ namespace llarp
}
};
- typedef std::unordered_map< PathInfo_t, Path*, PathInfoHash > PathMap_t;
+ using PathMap_t = std::unordered_map< PathInfo_t, Path*, PathInfoHash >;
PathMap_t m_Paths;
};
diff --git a/include/llarp/profiling.hpp b/include/llarp/profiling.hpp
index 120baf6e3..8c348b114 100644
--- a/include/llarp/profiling.hpp
+++ b/include/llarp/profiling.hpp
@@ -69,8 +69,8 @@ namespace llarp
MarkPathSuccess(path::Path* p);
private:
- typedef llarp::util::Lock lock_t;
- typedef llarp::util::Mutex mtx_t;
+ using lock_t = llarp::util::Lock;
+ using mtx_t = llarp::util::Mutex;
mtx_t m_ProfilesMutex;
std::map< RouterID, RouterProfile > m_Profiles;
};
diff --git a/include/llarp/router_id.hpp b/include/llarp/router_id.hpp
index 00359c07c..ef9a49a62 100644
--- a/include/llarp/router_id.hpp
+++ b/include/llarp/router_id.hpp
@@ -5,7 +5,7 @@
namespace llarp
{
- typedef AlignedBuffer< 32 > RouterID;
+ using RouterID = AlignedBuffer< 32 >;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/include/llarp/routing_endpoint.hpp b/include/llarp/routing_endpoint.hpp
index aa2389ceb..532af81e0 100644
--- a/include/llarp/routing_endpoint.hpp
+++ b/include/llarp/routing_endpoint.hpp
@@ -6,7 +6,7 @@
namespace llarp
{
- typedef AlignedBuffer< 32 > RoutingEndpoint_t;
+ using RoutingEndpoint_t = AlignedBuffer< 32 >;
/// Interface for end to end crypto between endpoints
struct IRoutingEndpoint
@@ -15,4 +15,4 @@ namespace llarp
};
} // namespace llarp
-#endif
\ No newline at end of file
+#endif
diff --git a/include/llarp/rpc.hpp b/include/llarp/rpc.hpp
index 8a08e8b2d..253b3fc47 100644
--- a/include/llarp/rpc.hpp
+++ b/include/llarp/rpc.hpp
@@ -41,9 +41,12 @@ namespace llarp
Start(const std::string& remote);
/// test if a router is valid
+ bool
+ VerifyRouter(const llarp::PubKey& pk);
+
+ /// do per second tick
void
- VerifyRouter(llarp::PubKey pkey,
- std::function< void(llarp::PubKey, bool) > handler);
+ Tick(llarp_time_t now);
private:
CallerImpl* m_Impl;
diff --git a/include/llarp/service/config.hpp b/include/llarp/service/config.hpp
index 1cf429d56..1f8d9cbe2 100644
--- a/include/llarp/service/config.hpp
+++ b/include/llarp/service/config.hpp
@@ -9,9 +9,9 @@ namespace llarp
{
struct Config
{
- typedef std::list< std::pair< std::string, std::string > >
- section_values_t;
- typedef std::pair< std::string, section_values_t > section_t;
+ using section_values_t =
+ std::list< std::pair< std::string, std::string > >;
+ using section_t = std::pair< std::string, section_values_t >;
std::list< section_t > services;
@@ -20,4 +20,4 @@ namespace llarp
};
} // namespace service
} // namespace llarp
-#endif
\ No newline at end of file
+#endif
diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp
index 0458f7669..a8d622c3c 100644
--- a/include/llarp/service/endpoint.hpp
+++ b/include/llarp/service/endpoint.hpp
@@ -137,8 +137,13 @@ namespace llarp
HandleDataMessage(const PathID_t&, ProtocolMessage* msg);
virtual bool
- ProcessDataMessage(__attribute__((unused)) ProtocolMessage* msg)
+ ProcessDataMessage(ProtocolMessage* msg)
{
+#ifdef TESTNET
+ llarp::LogInfo("Got message from ", msg->sender.Addr());
+#else
+ (void)msg;
+#endif
return true;
}
@@ -188,7 +193,7 @@ namespace llarp
bool
CheckPathIsDead(path::Path* p, llarp_time_t latency);
- typedef std::queue< PendingBuffer > PendingBufferQueue;
+ using PendingBufferQueue = std::queue< PendingBuffer >;
struct SendContext
{
@@ -326,7 +331,7 @@ namespace llarp
// passed a sendto context when we have a path established otherwise
// nullptr if the path was not made before the timeout
- typedef std::function< void(Address, OutboundContext*) > PathEnsureHook;
+ using PathEnsureHook = std::function< void(Address, OutboundContext*) >;
/// return false if we have already called this function before for this
/// address
diff --git a/include/llarp/service/handler.hpp b/include/llarp/service/handler.hpp
index 5c17ffe08..747580831 100644
--- a/include/llarp/service/handler.hpp
+++ b/include/llarp/service/handler.hpp
@@ -9,7 +9,7 @@ namespace llarp
{
namespace service
{
- typedef llarp::AlignedBuffer< 16 > ConvoTag;
+ using ConvoTag = llarp::AlignedBuffer< 16 >;
struct ProtocolMessage;
struct IDataHandler
diff --git a/include/llarp/service/protocol.hpp b/include/llarp/service/protocol.hpp
index 8d2a1b325..e22743900 100644
--- a/include/llarp/service/protocol.hpp
+++ b/include/llarp/service/protocol.hpp
@@ -17,7 +17,7 @@ namespace llarp
{
constexpr std::size_t MAX_PROTOCOL_MESSAGE_SIZE = 2048 * 2;
- typedef uint64_t ProtocolType;
+ using ProtocolType = uint64_t;
constexpr ProtocolType eProtocolText = 0UL;
constexpr ProtocolType eProtocolTraffic = 1UL;
diff --git a/include/llarp/service/vanity.hpp b/include/llarp/service/vanity.hpp
index 432225ad0..4f3a92d71 100644
--- a/include/llarp/service/vanity.hpp
+++ b/include/llarp/service/vanity.hpp
@@ -8,7 +8,7 @@ namespace llarp
{
/// hidden service address
- typedef llarp::AlignedBuffer< 16 > VanityNonce;
+ using VanityNonce = llarp::AlignedBuffer< 16 >;
} // namespace service
} // namespace llarp
-#endif
\ No newline at end of file
+#endif
diff --git a/include/llarp/string_view.hpp b/include/llarp/string_view.hpp
index 7cf1be992..5146664a4 100644
--- a/include/llarp/string_view.hpp
+++ b/include/llarp/string_view.hpp
@@ -6,7 +6,7 @@
#include
namespace llarp
{
- typedef std::string_view string_view;
+ using string_view = std::string_view;
static std::string
string_view_string(const string_view& v)
{
@@ -17,7 +17,7 @@ namespace llarp
#include
namespace llarp
{
- typedef std::string string_view;
+ using string_view = std::string;
static std::string
string_view_string(const string_view& v)
@@ -26,4 +26,4 @@ namespace llarp
};
} // namespace llarp
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/include/llarp/threading.hpp b/include/llarp/threading.hpp
index fb17ba3ac..5bf0ac944 100644
--- a/include/llarp/threading.hpp
+++ b/include/llarp/threading.hpp
@@ -34,9 +34,9 @@ namespace llarp
}
};
- typedef std::mutex mtx_t;
- typedef std::unique_lock< std::mutex > lock_t;
- typedef std::condition_variable cond_t;
+ using mtx_t = std::mutex;
+ using lock_t = std::unique_lock< std::mutex >;
+ using cond_t = std::condition_variable;
struct Mutex
{
diff --git a/include/llarp/timer.hpp b/include/llarp/timer.hpp
index c78e1e23d..5d887cf60 100644
--- a/include/llarp/timer.hpp
+++ b/include/llarp/timer.hpp
@@ -5,8 +5,11 @@
#include
#include
+#include
+
/** called with userptr, original timeout, left */
-typedef void (*llarp_timer_handler_func)(void *, uint64_t, uint64_t);
+using llarp_timer_handler_func =
+ std::function< void(void *, uint64_t, uint64_t) >;
struct llarp_timeout_job
{
diff --git a/include/llarp/types.hpp b/include/llarp/types.hpp
index abaaee29e..0705a92b4 100644
--- a/include/llarp/types.hpp
+++ b/include/llarp/types.hpp
@@ -3,7 +3,7 @@
#include
using llarp_proto_version_t = std::uint8_t;
-using llarp_time_t = std::uint64_t;
-using llarp_seconds_t = std::uint64_t;
+using llarp_time_t = std::uint64_t;
+using llarp_seconds_t = std::uint64_t;
#endif
diff --git a/include/tl/optional.hpp b/include/tl/optional.hpp
index 88ce30e42..7c6a4d669 100644
--- a/include/tl/optional.hpp
+++ b/include/tl/optional.hpp
@@ -24,68 +24,78 @@
#include
#include
-#if (defined(_MSC_VER) && _MSC_VER == 1900)
+#if(defined(_MSC_VER) && _MSC_VER == 1900)
#define TL_OPTIONAL_MSVC2015
#endif
-#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
- !defined(__clang__))
+#if(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 \
+ && !defined(__clang__))
#define TL_OPTIONAL_GCC49
#endif
-#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
- !defined(__clang__))
+#if(defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 \
+ && !defined(__clang__))
#define TL_OPTIONAL_GCC54
#endif
-#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
- !defined(__clang__))
+#if(defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 \
+ && !defined(__clang__))
#define TL_OPTIONAL_GCC55
#endif
-#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
- !defined(__clang__))
+#if(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 \
+ && !defined(__clang__))
// GCC < 5 doesn't support overloading on const&& for member functions
#define TL_OPTIONAL_NO_CONSTRR
// GCC < 5 doesn't support some standard C++11 type traits
-#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- std::has_trivial_copy_constructor::value
-#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
+ std::has_trivial_copy_constructor< T >::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
+ std::has_trivial_copy_assign< T >::value
// This one will be different for GCC 5.7 if it's ever supported
-#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
+#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \
+ std::is_trivially_destructible< T >::value
-// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
-// for non-copyable types
-#elif (defined(__GNUC__) && __GNUC__ < 8 && \
- !defined(__clang__))
+// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks
+// std::vector for non-copyable types
+#elif(defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
#ifndef TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
-namespace tl {
- namespace detail {
- template
- struct is_trivially_copy_constructible : std::is_trivially_copy_constructible{};
+namespace tl
+{
+ namespace detail
+ {
+ template < class T >
+ struct is_trivially_copy_constructible
+ : std::is_trivially_copy_constructible< T >
+ {
+ };
#ifdef _GLIBCXX_VECTOR
- template
- struct is_trivially_copy_constructible>
- : std::is_trivially_copy_constructible{};
-#endif
- }
-}
+ template < class T, class A >
+ struct is_trivially_copy_constructible< std::vector< T, A > >
+ : std::is_trivially_copy_constructible< T >
+ {
+ };
+#endif
+ } // namespace detail
+} // namespace tl
#endif
-#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- tl::detail::is_trivially_copy_constructible::value
-#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
- std::is_trivially_copy_assignable::value
-#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
+ tl::detail::is_trivially_copy_constructible< T >::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
+ std::is_trivially_copy_assignable< T >::value
+#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \
+ std::is_trivially_destructible< T >::value
#else
-#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
- std::is_trivially_copy_constructible::value
-#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
- std::is_trivially_copy_assignable::value
-#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
+ std::is_trivially_copy_constructible< T >::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
+ std::is_trivially_copy_assignable< T >::value
+#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) \
+ std::is_trivially_destructible< T >::value
#endif
#if __cplusplus > 201103L
@@ -93,8 +103,8 @@ namespace tl {
#endif
// constexpr implies const in C++11, not C++14
-#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \
- defined(TL_OPTIONAL_GCC49))
+#if(__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) \
+ || defined(TL_OPTIONAL_GCC49))
/// \exclude
#define TL_OPTIONAL_11_CONSTEXPR
#else
@@ -102,42 +112,58 @@ namespace tl {
#define TL_OPTIONAL_11_CONSTEXPR constexpr
#endif
-namespace tl {
+namespace tl
+{
#ifndef TL_MONOSTATE_INPLACE_MUTEX
#define TL_MONOSTATE_INPLACE_MUTEX
-/// \brief Used to represent an optional with no data; essentially a bool
-class monostate {};
-
-/// \brief A tag type to tell optional to construct its value in-place
-struct in_place_t {
- explicit in_place_t() = default;
-};
-/// \brief A tag to tell optional to construct its value in-place
-static constexpr in_place_t in_place{};
+ /// \brief Used to represent an optional with no data; essentially a bool
+ class monostate
+ {
+ };
+
+ /// \brief A tag type to tell optional to construct its value in-place
+ struct in_place_t
+ {
+ explicit in_place_t() = default;
+ };
+ /// \brief A tag to tell optional to construct its value in-place
+ static constexpr in_place_t in_place{};
#endif
-template class optional;
+ template < class T >
+ class optional;
-/// \exclude
-namespace detail {
+ /// \exclude
+ namespace detail
+ {
#ifndef TL_TRAITS_MUTEX
#define TL_TRAITS_MUTEX
-// C++14-style aliases for brevity
-template using remove_const_t = typename std::remove_const::type;
-template
-using remove_reference_t = typename std::remove_reference::type;
-template using decay_t = typename std::decay::type;
-template
-using enable_if_t = typename std::enable_if::type;
-template
-using conditional_t = typename std::conditional::type;
-
-// std::conjunction from C++17
-template struct conjunction : std::true_type {};
-template struct conjunction : B {};
-template
-struct conjunction
- : std::conditional, B>::type {};
+ // C++14-style aliases for brevity
+ template < class T >
+ using remove_const_t = typename std::remove_const< T >::type;
+ template < class T >
+ using remove_reference_t = typename std::remove_reference< T >::type;
+ template < class T >
+ using decay_t = typename std::decay< T >::type;
+ template < bool E, class T = void >
+ using enable_if_t = typename std::enable_if< E, T >::type;
+ template < bool B, class T, class F >
+ using conditional_t = typename std::conditional< B, T, F >::type;
+
+ // std::conjunction from C++17
+ template < class... >
+ struct conjunction : std::true_type
+ {
+ };
+ template < class B >
+ struct conjunction< B > : B
+ {
+ };
+ template < class B, class... Bs >
+ struct conjunction< B, Bs... >
+ : std::conditional< bool(B::value), conjunction< Bs... >, B >::type
+ {
+ };
#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
#define TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
@@ -147,323 +173,481 @@ struct conjunction
// which results in a hard-error when using it in a noexcept expression
// in some cases. This is a check to workaround the common failing case.
#ifdef TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
-template struct is_pointer_to_non_const_member_func : std::false_type{};
-template
-struct is_pointer_to_non_const_member_func : std::true_type{};
-template
-struct is_pointer_to_non_const_member_func : std::true_type{};
-template
-struct is_pointer_to_non_const_member_func : std::true_type{};
-template
-struct is_pointer_to_non_const_member_func : std::true_type{};
-template
-struct is_pointer_to_non_const_member_func : std::true_type{};
-template
-struct is_pointer_to_non_const_member_func : std::true_type{};
-
-template struct is_const_or_const_ref : std::false_type{};
-template struct is_const_or_const_ref : std::true_type{};
-template struct is_const_or_const_ref : std::true_type{};
+ template < class T >
+ struct is_pointer_to_non_const_member_func : std::false_type
+ {
+ };
+ template < class T, class Ret, class... Args >
+ struct is_pointer_to_non_const_member_func< Ret (T::*)(Args...) >
+ : std::true_type
+ {
+ };
+ template < class T, class Ret, class... Args >
+ struct is_pointer_to_non_const_member_func< Ret (T::*)(Args...) & >
+ : std::true_type
+ {
+ };
+ template < class T, class Ret, class... Args >
+ struct is_pointer_to_non_const_member_func< Ret (T::*)(Args...) && >
+ : std::true_type
+ {
+ };
+ template < class T, class Ret, class... Args >
+ struct is_pointer_to_non_const_member_func< Ret (T::*)(Args...) volatile >
+ : std::true_type
+ {
+ };
+ template < class T, class Ret, class... Args >
+ struct is_pointer_to_non_const_member_func< Ret (T::*)(Args...) volatile & >
+ : std::true_type
+ {
+ };
+ template < class T, class Ret, class... Args >
+ struct is_pointer_to_non_const_member_func< Ret (T::*)(
+ Args...) volatile && > : std::true_type
+ {
+ };
+
+ template < class T >
+ struct is_const_or_const_ref : std::false_type
+ {
+ };
+ template < class T >
+ struct is_const_or_const_ref< T const & > : std::true_type
+ {
+ };
+ template < class T >
+ struct is_const_or_const_ref< T const > : std::true_type
+ {
+ };
#endif
-// std::invoke from C++17
-// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
-template ::value
- && is_const_or_const_ref::value)>,
+ typename =
+ enable_if_t< !(is_pointer_to_non_const_member_func< Fn >::value
+ && is_const_or_const_ref< Args... >::value) >,
#endif
- typename = enable_if_t>::value>,
- int = 0>
-constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
- noexcept(std::mem_fn(f)(std::forward(args)...)))
- -> decltype(std::mem_fn(f)(std::forward(args)...)) {
- return std::mem_fn(f)(std::forward(args)...);
-}
-
-template >::value>>
-constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
- noexcept(std::forward(f)(std::forward(args)...)))
- -> decltype(std::forward(f)(std::forward(args)...)) {
- return std::forward(f)(std::forward(args)...);
-}
-
-// std::invoke_result from C++17
-template struct invoke_result_impl;
-
-template
-struct invoke_result_impl<
- F, decltype(detail::invoke(std::declval(), std::declval()...), void()),
- Us...> {
- using type = decltype(detail::invoke(std::declval(), std::declval()...));
-};
-
-template
-using invoke_result = invoke_result_impl;
-
-template
-using invoke_result_t = typename invoke_result::type;
+ typename =
+ enable_if_t< std::is_member_pointer< decay_t< Fn > >::value >,
+ int = 0 >
+ constexpr auto
+ invoke(Fn &&f, Args &&... args) noexcept(
+ noexcept(std::mem_fn(f)(std::forward< Args >(args)...)))
+ -> decltype(std::mem_fn(f)(std::forward< Args >(args)...))
+ {
+ return std::mem_fn(f)(std::forward< Args >(args)...);
+ }
+
+ template < typename Fn, typename... Args,
+ typename = enable_if_t<
+ !std::is_member_pointer< decay_t< Fn > >::value > >
+ constexpr auto
+ invoke(Fn &&f, Args &&... args) noexcept(
+ noexcept(std::forward< Fn >(f)(std::forward< Args >(args)...)))
+ -> decltype(std::forward< Fn >(f)(std::forward< Args >(args)...))
+ {
+ return std::forward< Fn >(f)(std::forward< Args >(args)...);
+ }
+
+ // std::invoke_result from C++17
+ template < class F, class, class... Us >
+ struct invoke_result_impl;
+
+ template < class F, class... Us >
+ struct invoke_result_impl< F,
+ decltype(detail::invoke(std::declval< F >(),
+ std::declval< Us >()...),
+ void()),
+ Us... >
+ {
+ using type = decltype(
+ detail::invoke(std::declval< F >(), std::declval< Us >()...));
+ };
+
+ template < class F, class... Us >
+ using invoke_result = invoke_result_impl< F, void, Us... >;
+
+ template < class F, class... Us >
+ using invoke_result_t = typename invoke_result< F, Us... >::type;
#endif
-// std::void_t from C++17
-template struct voider { using type = void; };
-template using void_t = typename voider::type;
-
-// Trait for checking if a type is a tl::optional
-template struct is_optional_impl : std::false_type {};
-template struct is_optional_impl> : std::true_type {};
-template using is_optional = is_optional_impl>;
-
-// Change void to tl::monostate
-template
-using fixup_void = conditional_t::value, monostate, U>;
-
-template >
-using get_map_return = optional>>;
-
-// Check if invoking F for some Us returns void
-template struct returns_void_impl;
-template
-struct returns_void_impl>, U...>
- : std::is_void> {};
-template
-using returns_void = returns_void_impl;
-
-template
-using enable_if_ret_void = enable_if_t::value>;
-
-template
-using disable_if_ret_void = enable_if_t::value>;
-
-template
-using enable_forward_value =
- detail::enable_if_t::value &&
- !std::is_same, in_place_t>::value &&
- !std::is_same, detail::decay_t>::value>;
-
-template
-using enable_from_other = detail::enable_if_t<
- std::is_constructible::value &&
- !std::is_constructible &>::value &&
- !std::is_constructible &&>::value &&
- !std::is_constructible &>::value &&
- !std::is_constructible &&>::value &&
- !std::is_convertible &, T>::value &&
- !std::is_convertible &&, T>::value &&
- !std::is_convertible &, T>::value &&
- !std::is_convertible &&, T>::value>;
-
-template
-using enable_assign_forward = detail::enable_if_t<
- !std::is_same, detail::decay_t>::value &&
- !detail::conjunction,
- std::is_same>>::value &&
- std::is_constructible::value && std::is_assignable::value>;
-
-template
-using enable_assign_from_other = detail::enable_if_t<
- std::is_constructible::value &&
- std::is_assignable::value &&
- !std::is_constructible &>::value &&
- !std::is_constructible &&>::value &&
- !std::is_constructible &>::value &&
- !std::is_constructible &&>::value &&
- !std::is_convertible &, T>::value &&
- !std::is_convertible &&, T>::value &&
- !std::is_convertible &, T>::value &&
- !std::is_convertible &&, T>::value &&
- !std::is_assignable &>::value &&
- !std::is_assignable &&>::value &&
- !std::is_assignable &>::value &&
- !std::is_assignable &&>::value>;
+ // std::void_t from C++17
+ template < class... >
+ struct voider
+ {
+ using type = void;
+ };
+ template < class... Ts >
+ using void_t = typename voider< Ts... >::type;
+
+ // Trait for checking if a type is a tl::optional
+ template < class T >
+ struct is_optional_impl : std::false_type
+ {
+ };
+ template < class T >
+ struct is_optional_impl< optional< T > > : std::true_type
+ {
+ };
+ template < class T >
+ using is_optional = is_optional_impl< decay_t< T > >;
+
+ // Change void to tl::monostate
+ template < class U >
+ using fixup_void = conditional_t< std::is_void< U >::value, monostate, U >;
+
+ template < class F, class U, class = invoke_result_t< F, U > >
+ using get_map_return = optional< fixup_void< invoke_result_t< F, U > > >;
+
+ // Check if invoking F for some Us returns void
+ template < class F, class = void, class... U >
+ struct returns_void_impl;
+ template < class F, class... U >
+ struct returns_void_impl< F, void_t< invoke_result_t< F, U... > >, U... >
+ : std::is_void< invoke_result_t< F, U... > >
+ {
+ };
+ template < class F, class... U >
+ using returns_void = returns_void_impl< F, void, U... >;
+
+ template < class T, class... U >
+ using enable_if_ret_void = enable_if_t< returns_void< T &&, U... >::value >;
+
+ template < class T, class... U >
+ using disable_if_ret_void =
+ enable_if_t< !returns_void< T &&, U... >::value >;
+
+ template < class T, class U >
+ using enable_forward_value = detail::enable_if_t<
+ std::is_constructible< T, U && >::value
+ && !std::is_same< detail::decay_t< U >, in_place_t >::value
+ && !std::is_same< optional< T >, detail::decay_t< U > >::value >;
+
+ template < class T, class U, class Other >
+ using enable_from_other = detail::enable_if_t<
+ std::is_constructible< T, Other >::value
+ && !std::is_constructible< T, optional< U > & >::value
+ && !std::is_constructible< T, optional< U > && >::value
+ && !std::is_constructible< T, const optional< U > & >::value
+ && !std::is_constructible< T, const optional< U > && >::value
+ && !std::is_convertible< optional< U > &, T >::value
+ && !std::is_convertible< optional< U > &&, T >::value
+ && !std::is_convertible< const optional< U > &, T >::value
+ && !std::is_convertible< const optional< U > &&, T >::value >;
+
+ template < class T, class U >
+ using enable_assign_forward = detail::enable_if_t<
+ !std::is_same< optional< T >, detail::decay_t< U > >::value
+ && !detail::conjunction<
+ std::is_scalar< T >,
+ std::is_same< T, detail::decay_t< U > > >::value
+ && std::is_constructible< T, U >::value
+ && std::is_assignable< T &, U >::value >;
+
+ template < class T, class U, class Other >
+ using enable_assign_from_other = detail::enable_if_t<
+ std::is_constructible< T, Other >::value
+ && std::is_assignable< T &, Other >::value
+ && !std::is_constructible< T, optional< U > & >::value
+ && !std::is_constructible< T, optional< U > && >::value
+ && !std::is_constructible< T, const optional< U > & >::value
+ && !std::is_constructible< T, const optional< U > && >::value
+ && !std::is_convertible< optional< U > &, T >::value
+ && !std::is_convertible< optional< U > &&, T >::value
+ && !std::is_convertible< const optional< U > &, T >::value
+ && !std::is_convertible< const optional< U > &&, T >::value
+ && !std::is_assignable< T &, optional< U > & >::value
+ && !std::is_assignable< T &, optional< U > && >::value
+ && !std::is_assignable< T &, const optional< U > & >::value
+ && !std::is_assignable< T &, const optional< U > && >::value >;
#ifdef _MSC_VER
-// TODO make a version which works with MSVC
-template struct is_swappable : std::true_type {};
-
-template struct is_nothrow_swappable : std::true_type {};
+ // TODO make a version which works with MSVC
+ template < class T, class U = T >
+ struct is_swappable : std::true_type
+ {
+ };
+
+ template < class T, class U = T >
+ struct is_nothrow_swappable : std::true_type
+ {
+ };
#else
-// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
-namespace swap_adl_tests {
-// if swap ADL finds this then it would call std::swap otherwise (same
-// signature)
-struct tag {};
-
-template tag swap(T &, T &);
-template tag swap(T (&a)[N], T (&b)[N]);
-
-// helper functions to test if an unqualified swap is possible, and if it
-// becomes std::swap
-template std::false_type can_swap(...) noexcept(false);
-template (), std::declval()))>
-std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(),
- std::declval())));
-
-template std::false_type uses_std(...);
-template
-std::is_same(), std::declval())), tag>
-uses_std(int);
-
-template
-struct is_std_swap_noexcept
- : std::integral_constant::value &&
- std::is_nothrow_move_assignable::value> {};
-
-template
-struct is_std_swap_noexcept : is_std_swap_noexcept {};
-
-template
-struct is_adl_swap_noexcept
- : std::integral_constant(0))> {};
-} // namespace swap_adl_tests
-
-template
-struct is_swappable
- : std::integral_constant<
- bool,
- decltype(detail::swap_adl_tests::can_swap(0))::value &&
- (!decltype(detail::swap_adl_tests::uses_std(0))::value ||
- (std::is_move_assignable::value &&
- std::is_move_constructible::value))> {};
-
-template
-struct is_swappable
- : std::integral_constant<
- bool,
- decltype(detail::swap_adl_tests::can_swap(0))::value &&
- (!decltype(
- detail::swap_adl_tests::uses_std(0))::value ||
- is_swappable::value)> {};
-
-template
-struct is_nothrow_swappable
- : std::integral_constant<
- bool,
- is_swappable::value &&
- ((decltype(detail::swap_adl_tests::uses_std(0))::value
- &&detail::swap_adl_tests::is_std_swap_noexcept::value) ||
- (!decltype(detail::swap_adl_tests::uses_std(0))::value &&
- detail::swap_adl_tests::is_adl_swap_noexcept::value))> {
-};
+ // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
+ namespace swap_adl_tests
+ {
+ // if swap ADL finds this then it would call std::swap otherwise (same
+ // signature)
+ struct tag
+ {
+ };
+
+ template < class T >
+ tag
+ swap(T &, T &);
+ template < class T, std::size_t N >
+ tag swap(T (&a)[N], T (&b)[N]);
+
+ // helper functions to test if an unqualified swap is possible, and if it
+ // becomes std::swap
+ template < class, class >
+ std::false_type
+ can_swap(...) noexcept(false);
+ template < class T, class U,
+ class = decltype(swap(std::declval< T & >(),
+ std::declval< U & >())) >
+ std::true_type
+ can_swap(int) noexcept(noexcept(swap(std::declval< T & >(),
+ std::declval< U & >())));
+
+ template < class, class >
+ std::false_type
+ uses_std(...);
+ template < class T, class U >
+ std::is_same<
+ decltype(swap(std::declval< T & >(), std::declval< U & >())), tag >
+ uses_std(int);
+
+ template < class T >
+ struct is_std_swap_noexcept
+ : std::integral_constant<
+ bool,
+ std::is_nothrow_move_constructible< T >::value
+ && std::is_nothrow_move_assignable< T >::value >
+ {
+ };
+
+ template < class T, std::size_t N >
+ struct is_std_swap_noexcept< T[N] > : is_std_swap_noexcept< T >
+ {
+ };
+
+ template < class T, class U >
+ struct is_adl_swap_noexcept
+ : std::integral_constant< bool, noexcept(can_swap< T, U >(0)) >
+ {
+ };
+ } // namespace swap_adl_tests
+
+ template < class T, class U = T >
+ struct is_swappable
+ : std::integral_constant<
+ bool,
+ decltype(detail::swap_adl_tests::can_swap< T, U >(0))::value
+ && (!decltype(
+ detail::swap_adl_tests::uses_std< T, U >(0))::value
+ || (std::is_move_assignable< T >::value
+ && std::is_move_constructible< T >::value)) >
+ {
+ };
+
+ template < class T, std::size_t N >
+ struct is_swappable< T[N], T[N] >
+ : std::integral_constant<
+ bool,
+ decltype(detail::swap_adl_tests::can_swap< T[N], T[N] >(0))::value
+ && (!decltype(detail::swap_adl_tests::uses_std< T[N], T[N] >(
+ 0))::value
+ || is_swappable< T, T >::value) >
+ {
+ };
+
+ template < class T, class U = T >
+ struct is_nothrow_swappable
+ : std::integral_constant<
+ bool,
+ is_swappable< T, U >::value
+ && ((decltype(detail::swap_adl_tests::uses_std< T, U >(
+ 0))::value &&detail::swap_adl_tests::
+ is_std_swap_noexcept< T >::value)
+ || (!decltype(detail::swap_adl_tests::uses_std< T, U >(
+ 0))::value &&detail::swap_adl_tests::
+ is_adl_swap_noexcept< T, U >::value)) >
+ {
+ };
#endif
-// The storage base manages the actual storage, and correctly propagates
-// trivial destruction from T. This case is for when T is not trivially
-// destructible.
-template ::value>
-struct optional_storage_base {
- TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
- : m_dummy(), m_has_value(false) {}
-
- template
- TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
- : m_value(std::forward(u)...), m_has_value(true) {}
-
- ~optional_storage_base() {
- if (m_has_value) {
- m_value.~T();
- m_has_value = false;
- }
- }
-
- struct dummy {};
- union {
- dummy m_dummy;
- T m_value;
- };
-
- bool m_has_value;
-};
-
-// This case is for when T is trivially destructible.
-template struct optional_storage_base {
- TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
- : m_dummy(), m_has_value(false) {}
-
- template
- TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
- : m_value(std::forward(u)...), m_has_value(true) {}
-
- // No destructor, so this class is trivially destructible
-
- struct dummy {};
- union {
- dummy m_dummy;
- T m_value;
- };
+ // The storage base manages the actual storage, and correctly propagates
+ // trivial destruction from T. This case is for when T is not trivially
+ // destructible.
+ template < class T, bool = ::std::is_trivially_destructible< T >::value >
+ struct optional_storage_base
+ {
+ TL_OPTIONAL_11_CONSTEXPR
+ optional_storage_base() noexcept
+ : m_dummy(), m_has_value(false)
+ {
+ }
- bool m_has_value = false;
-};
+ template < class... U >
+ TL_OPTIONAL_11_CONSTEXPR
+ optional_storage_base(in_place_t, U &&... u)
+ : m_value(std::forward< U >(u)...), m_has_value(true)
+ {
+ }
-// This base class provides some handy member functions which can be used in
-// further derived classes
-template struct optional_operations_base : optional_storage_base {
- using optional_storage_base::optional_storage_base;
+ ~optional_storage_base()
+ {
+ if(m_has_value)
+ {
+ m_value.~T();
+ m_has_value = false;
+ }
+ }
- void hard_reset() noexcept {
- get().~T();
- this->m_has_value = false;
- }
+ struct dummy
+ {
+ };
+ union {
+ dummy m_dummy;
+ T m_value;
+ };
+
+ bool m_has_value;
+ };
+
+ // This case is for when T is trivially destructible.
+ template < class T >
+ struct optional_storage_base< T, true >
+ {
+ TL_OPTIONAL_11_CONSTEXPR
+ optional_storage_base() noexcept
+ : m_dummy(), m_has_value(false)
+ {
+ }
- template void construct(Args &&... args) noexcept {
- new (std::addressof(this->m_value)) T(std::forward(args)...);
- this->m_has_value = true;
- }
+ template < class... U >
+ TL_OPTIONAL_11_CONSTEXPR
+ optional_storage_base(in_place_t, U &&... u)
+ : m_value(std::forward< U >(u)...), m_has_value(true)
+ {
+ }
- template void assign(Opt &&rhs) {
- if (this->has_value()) {
- if (rhs.has_value()) {
- this->m_value = std::forward(rhs).get();
- } else {
- this->m_value.~T();
+ // No destructor, so this class is trivially destructible
+
+ struct dummy
+ {
+ };
+ union {
+ dummy m_dummy;
+ T m_value;
+ };
+
+ bool m_has_value = false;
+ };
+
+ // This base class provides some handy member functions which can be used in
+ // further derived classes
+ template < class T >
+ struct optional_operations_base : optional_storage_base< T >
+ {
+ using optional_storage_base< T >::optional_storage_base;
+
+ void
+ hard_reset() noexcept
+ {
+ get().~T();
this->m_has_value = false;
}
- }
- else if (rhs.has_value()) {
- construct(std::forward(rhs).get());
- }
- }
+ template < class... Args >
+ void
+ construct(Args &&... args) noexcept
+ {
+ new(std::addressof(this->m_value)) T(std::forward< Args >(args)...);
+ this->m_has_value = true;
+ }
- bool has_value() const { return this->m_has_value; }
+ template < class Opt >
+ void
+ assign(Opt &&rhs)
+ {
+ if(this->has_value())
+ {
+ if(rhs.has_value())
+ {
+ this->m_value = std::forward< Opt >(rhs).get();
+ }
+ else
+ {
+ this->m_value.~T();
+ this->m_has_value = false;
+ }
+ }
+
+ else if(rhs.has_value())
+ {
+ construct(std::forward< Opt >(rhs).get());
+ }
+ }
- TL_OPTIONAL_11_CONSTEXPR T &get() & { return this->m_value; }
- TL_OPTIONAL_11_CONSTEXPR const T &get() const & { return this->m_value; }
- TL_OPTIONAL_11_CONSTEXPR T &&get() && { return std::move(this->m_value); }
+ bool
+ has_value() const
+ {
+ return this->m_has_value;
+ }
+
+ TL_OPTIONAL_11_CONSTEXPR T &
+ get() &
+ {
+ return this->m_value;
+ }
+ TL_OPTIONAL_11_CONSTEXPR const T &
+ get() const &
+ {
+ return this->m_value;
+ }
+ TL_OPTIONAL_11_CONSTEXPR T &&
+ get() &&
+ {
+ return std::move(this->m_value);
+ }
#ifndef TL_OPTIONAL_NO_CONSTRR
- constexpr const T &&get() const && { return std::move(this->m_value); }
+ constexpr const T &&
+ get() const &&
+ {
+ return std::move(this->m_value);
+ }
#endif
-};
-
-// This class manages conditionally having a trivial copy constructor
-// This specialization is for when T is trivially copy constructible
-template
-struct optional_copy_base : optional_operations_base {
- using optional_operations_base::optional_operations_base;
-};
-
-// This specialization is for when T is not trivially copy constructible
-template
-struct optional_copy_base : optional_operations_base {
- using optional_operations_base::optional_operations_base;
-
- optional_copy_base() = default;
- optional_copy_base(const optional_copy_base &rhs) {
- if (rhs.has_value()) {
- this->construct(rhs.get());
- } else {
- this->m_has_value = false;
- }
- }
+ };
+
+ // This class manages conditionally having a trivial copy constructor
+ // This specialization is for when T is trivially copy constructible
+ template < class T, bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) >
+ struct optional_copy_base : optional_operations_base< T >
+ {
+ using optional_operations_base< T >::optional_operations_base;
+ };
+
+ // This specialization is for when T is not trivially copy constructible
+ template < class T >
+ struct optional_copy_base< T, false > : optional_operations_base< T >
+ {
+ using optional_operations_base< T >::optional_operations_base;
+
+ optional_copy_base() = default;
+ optional_copy_base(const optional_copy_base &rhs)
+ {
+ if(rhs.has_value())
+ {
+ this->construct(rhs.get());
+ }
+ else
+ {
+ this->m_has_value = false;
+ }
+ }
- optional_copy_base(optional_copy_base &&rhs) = default;
- optional_copy_base &operator=(const optional_copy_base &rhs) = default;
- optional_copy_base &operator=(optional_copy_base &&rhs) = default;
-};
+ optional_copy_base(optional_copy_base &&rhs) = default;
+ optional_copy_base &
+ operator=(const optional_copy_base &rhs) = default;
+ optional_copy_base &
+ operator=(optional_copy_base &&rhs) = default;
+ };
// This class manages conditionally having a trivial move constructor
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
@@ -471,54 +655,71 @@ struct optional_copy_base : optional_operations_base {
// have to make do with a non-trivial move constructor even if T is trivially
// move constructible
#ifndef TL_OPTIONAL_GCC49
-template ::value>
-struct optional_move_base : optional_copy_base {
- using optional_copy_base::optional_copy_base;
-};
+ template < class T,
+ bool = std::is_trivially_move_constructible< T >::value >
+ struct optional_move_base : optional_copy_base< T >
+ {
+ using optional_copy_base< T >::optional_copy_base;
+ };
#else
-template struct optional_move_base;
+ template < class T, bool = false >
+ struct optional_move_base;
#endif
-template struct optional_move_base : optional_copy_base {
- using optional_copy_base::optional_copy_base;
-
- optional_move_base() = default;
- optional_move_base(const optional_move_base &rhs) = default;
-
- optional_move_base(optional_move_base &&rhs) noexcept(
- std::is_nothrow_move_constructible::value) {
- if (rhs.has_value()) {
- this->construct(std::move(rhs.get()));
- } else {
- this->m_has_value = false;
- }
- }
- optional_move_base &operator=(const optional_move_base &rhs) = default;
- optional_move_base &operator=(optional_move_base &&rhs) = default;
-};
-
-// This class manages conditionally having a trivial copy assignment operator
-template
-struct optional_copy_assign_base : optional_move_base {
- using optional_move_base::optional_move_base;
-};
-
-template
-struct optional_copy_assign_base : optional_move_base {
- using optional_move_base::optional_move_base;
-
- optional_copy_assign_base() = default;
- optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
-
- optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
- optional_copy_assign_base &operator=(const optional_copy_assign_base &rhs) {
- this->assign(rhs);
- return *this;
- }
- optional_copy_assign_base &
- operator=(optional_copy_assign_base &&rhs) = default;
-};
+ template < class T >
+ struct optional_move_base< T, false > : optional_copy_base< T >
+ {
+ using optional_copy_base< T >::optional_copy_base;
+
+ optional_move_base() = default;
+ optional_move_base(const optional_move_base &rhs) = default;
+
+ optional_move_base(optional_move_base &&rhs) noexcept(
+ std::is_nothrow_move_constructible< T >::value)
+ {
+ if(rhs.has_value())
+ {
+ this->construct(std::move(rhs.get()));
+ }
+ else
+ {
+ this->m_has_value = false;
+ }
+ }
+ optional_move_base &
+ operator=(const optional_move_base &rhs) = default;
+ optional_move_base &
+ operator=(optional_move_base &&rhs) = default;
+ };
+
+ // This class manages conditionally having a trivial copy assignment
+ // operator
+ template < class T,
+ bool = TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T)
+ && TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)
+ && TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) >
+ struct optional_copy_assign_base : optional_move_base< T >
+ {
+ using optional_move_base< T >::optional_move_base;
+ };
+
+ template < class T >
+ struct optional_copy_assign_base< T, false > : optional_move_base< T >
+ {
+ using optional_move_base< T >::optional_move_base;
+
+ optional_copy_assign_base() = default;
+ optional_copy_assign_base(const optional_copy_assign_base &rhs) = default;
+
+ optional_copy_assign_base(optional_copy_assign_base &&rhs) = default;
+ optional_copy_assign_base &
+ operator=(const optional_copy_assign_base &rhs)
+ {
+ this->assign(rhs);
+ return *this;
+ }
+ optional_copy_assign_base &
+ operator=(optional_copy_assign_base &&rhs) = default;
+ };
// This class manages conditionally having a trivial move assignment operator
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
@@ -526,1826 +727,2302 @@ struct optional_copy_assign_base : optional_move_base {
// to make do with a non-trivial move assignment operator even if T is trivially
// move assignable
#ifndef TL_OPTIONAL_GCC49
-template ::value
- &&std::is_trivially_move_constructible::value
- &&std::is_trivially_move_assignable::value>
-struct optional_move_assign_base : optional_copy_assign_base {
- using optional_copy_assign_base::optional_copy_assign_base;
-};
+ template < class T,
+ bool = std::is_trivially_destructible< T >::value
+ &&std::is_trivially_move_constructible< T >::value
+ &&std::is_trivially_move_assignable< T >::value >
+ struct optional_move_assign_base : optional_copy_assign_base< T >
+ {
+ using optional_copy_assign_base< T >::optional_copy_assign_base;
+ };
#else
-template struct optional_move_assign_base;
+ template < class T, bool = false >
+ struct optional_move_assign_base;
#endif
-template
-struct optional_move_assign_base : optional_copy_assign_base {
- using optional_copy_assign_base::optional_copy_assign_base;
+ template < class T >
+ struct optional_move_assign_base< T, false >
+ : optional_copy_assign_base< T >
+ {
+ using optional_copy_assign_base< T >::optional_copy_assign_base;
- optional_move_assign_base() = default;
- optional_move_assign_base(const optional_move_assign_base &rhs) = default;
+ optional_move_assign_base() = default;
+ optional_move_assign_base(const optional_move_assign_base &rhs) = default;
- optional_move_assign_base(optional_move_assign_base &&rhs) = default;
+ optional_move_assign_base(optional_move_assign_base &&rhs) = default;
- optional_move_assign_base &
- operator=(const optional_move_assign_base &rhs) = default;
+ optional_move_assign_base &
+ operator=(const optional_move_assign_base &rhs) = default;
- optional_move_assign_base &
- operator=(optional_move_assign_base &&rhs) noexcept(
- std::is_nothrow_move_constructible::value
- &&std::is_nothrow_move_assignable::value) {
- this->assign(std::move(rhs));
- return *this;
- }
-};
-
-// optional_delete_ctor_base will conditionally delete copy and move
-// constructors depending on whether T is copy/move constructible
-template ::value,
- bool EnableMove = std::is_move_constructible::value>
-struct optional_delete_ctor_base {
- optional_delete_ctor_base() = default;
- optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
- optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
- optional_delete_ctor_base &
- operator=(const optional_delete_ctor_base &) = default;
- optional_delete_ctor_base &
- operator=(optional_delete_ctor_base &&) noexcept = default;
-};
-
-template struct optional_delete_ctor_base {
- optional_delete_ctor_base() = default;
- optional_delete_ctor_base(const optional_delete_ctor_base &) = default;
- optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
- optional_delete_ctor_base &
- operator=(const optional_delete_ctor_base &) = default;
- optional_delete_ctor_base &
- operator=(optional_delete_ctor_base &&) noexcept = default;
-};
-
-template struct optional_delete_ctor_base {
- optional_delete_ctor_base() = default;
- optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
- optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = default;
- optional_delete_ctor_base &
- operator=(const optional_delete_ctor_base &) = default;
- optional_delete_ctor_base &
- operator=(optional_delete_ctor_base &&) noexcept = default;
-};
-
-template struct optional_delete_ctor_base {
- optional_delete_ctor_base() = default;
- optional_delete_ctor_base(const optional_delete_ctor_base &) = delete;
- optional_delete_ctor_base(optional_delete_ctor_base &&) noexcept = delete;
- optional_delete_ctor_base &
- operator=(const optional_delete_ctor_base &) = default;
- optional_delete_ctor_base &
- operator=(optional_delete_ctor_base &&) noexcept = default;
-};
-
-// optional_delete_assign_base will conditionally delete copy and move
-// constructors depending on whether T is copy/move constructible + assignable
-template ::value &&
- std::is_copy_assignable::value),
- bool EnableMove = (std::is_move_constructible::value &&
- std::is_move_assignable::value)>
-struct optional_delete_assign_base {
- optional_delete_assign_base() = default;
- optional_delete_assign_base(const optional_delete_assign_base &) = default;
- optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
- default;
- optional_delete_assign_base &
- operator=(const optional_delete_assign_base &) = default;
- optional_delete_assign_base &
- operator=(optional_delete_assign_base &&) noexcept = default;
-};
-
-template struct optional_delete_assign_base {
- optional_delete_assign_base() = default;
- optional_delete_assign_base(const optional_delete_assign_base &) = default;
- optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
- default;
- optional_delete_assign_base &
- operator=(const optional_delete_assign_base &) = default;
- optional_delete_assign_base &
- operator=(optional_delete_assign_base &&) noexcept = delete;
-};
-
-template struct optional_delete_assign_base {
- optional_delete_assign_base() = default;
- optional_delete_assign_base(const optional_delete_assign_base &) = default;
- optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
- default;
- optional_delete_assign_base &
- operator=(const optional_delete_assign_base &) = delete;
- optional_delete_assign_base &
- operator=(optional_delete_assign_base &&) noexcept = default;
-};
-
-template struct optional_delete_assign_base {
- optional_delete_assign_base() = default;
- optional_delete_assign_base(const optional_delete_assign_base &) = default;
- optional_delete_assign_base(optional_delete_assign_base &&) noexcept =
- default;
- optional_delete_assign_base &
- operator=(const optional_delete_assign_base &) = delete;
- optional_delete_assign_base &
- operator=(optional_delete_assign_base &&) noexcept = delete;
-};
-
-} // namespace detail
-
-/// \brief A tag type to represent an empty optional
-struct nullopt_t {
- struct do_not_use {};
- constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept {}
-};
-/// \brief Represents an empty optional
-/// \synopsis static constexpr nullopt_t nullopt;
-///
-/// *Examples*:
-/// ```
-/// tl::optional a = tl::nullopt;
-/// void foo (tl::optional);
-/// foo(tl::nullopt); //pass an empty optional
-/// ```
-static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
- nullopt_t::do_not_use{}};
-
-class bad_optional_access : public std::exception {
-public:
- bad_optional_access() = default;
- const char *what() const noexcept { return "Optional has no value"; }
-};
-
-/// An optional object is an object that contains the storage for another
-/// object and manages the lifetime of this contained object, if any. The
-/// contained object may be initialized after the optional object has been
-/// initialized, and may be destroyed before the optional object has been
-/// destroyed. The initialization state of the contained object is tracked by
-/// the optional object.
-template
-class optional : private detail::optional_move_assign_base,
- private detail::optional_delete_ctor_base,
- private detail::optional_delete_assign_base {
- using base = detail::optional_move_assign_base