diff --git a/.travis.yml b/.travis.yml
index 1831c829..5e046229 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,7 +12,7 @@ node_js:
   - "12.14.1"
 
 before_install:
-  - export CXX="g++-4.9" CC="gcc-4.9"
+  - export CXX="clang-9.0" CC="clang++-9.0"
 
 script:
   - npm run standard
@@ -31,5 +31,5 @@ addons:
     sources:
     - ubuntu-toolchain-r-test
     packages:
-    - gcc-4.9
-    - g++-4.9
+    - clang-9.0
+    - clang++-9.0
diff --git a/appveyor.yml b/appveyor.yml
index aa43e41e..132e2c69 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-image: Visual Studio 2015
+image: Visual Studio 2017
 
 environment:
   matrix:
diff --git a/binding.gyp b/binding.gyp
index 249e9e82..85981bbb 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -67,7 +67,9 @@
     ],
 
     "variables": {
-        "tests": 0
+        "tests": 0,
+        "STANDARD": 17,
+        "MACOSX_DEPLOYMENT_TARGET": "10.8"
     },
 
     "conditions": [
@@ -100,20 +102,19 @@
                 "conditions": [
                     ['OS=="mac"', {
                         'cflags': [
-                            '-mmacosx-version-min=10.8'
+                            "-mmacosx-version-min=<(MACOSX_DEPLOYMENT_TARGET)"
                         ],
                         "xcode_settings": {
                             "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
-                            'MACOSX_DEPLOYMENT_TARGET': '10.8',
+                            'MACOSX_DEPLOYMENT_TARGET': '<(MACOSX_DEPLOYMENT_TARGET)',
                         }
                     }]
                 ]
             }]
         }]
     ],
-
     "target_defaults": {
-        "cflags_cc": ["-std=c++11"],
+        "cflags_cc": [ "-std=c++<(STANDARD)" ],
         "conditions": [
             ['OS=="mac"', {
                 "xcode_settings": {
@@ -129,6 +130,40 @@
                     "NOMINMAX"
                 ],
             }]
-        ]
-    }
+        ],
+        'default_configuration': 'Release',
+        'configurations': {
+          # Release Settings
+          'Release': {
+            'defines': [ 'NDEBUG' ],
+            "cflags": [ "-fno-exceptions", "-Ofast" ],
+            "cflags_cc": [ "-fno-exceptions", "-Ofast", "-std=c++<(STANDARD)" ],
+            "xcode_settings": {
+              'GCC_OPTIMIZATION_LEVEL': '3', # stop gyp from defaulting to -Os
+              "CLANG_CXX_LIBRARY": "libc++",
+              "CLANG_CXX_LANGUAGE_STANDARD": "c++<(STANDARD)",
+              'MACOSX_DEPLOYMENT_TARGET': "<(MACOSX_DEPLOYMENT_TARGET)"
+            }, # XCODE
+            "msvs_settings": {
+              "VCCLCompilerTool": {
+                'ExceptionHandling': 0,               # /EHsc
+                'MultiProcessorCompilation': 'true',
+                'RuntimeTypeInfo': 'false',
+                'Optimization': 3,              # full optimizations /O2  ==  /Og /Oi /Ot /Oy /Ob2 /GF /Gy
+                'StringPooling': 'true',        # pool string literals
+                "AdditionalOptions": [
+                  # C++ standard
+                  "/std:c++<(STANDARD)",
+
+                  # Optimizations
+                  "/O2",
+                  # "/Ob3",  # aggressive inline
+                  "/GL",   # whole Program Optimization  # /LTCG is implied with /GL.
+                  "/DNDEBUG"  # turn off asserts
+                ],
+              }
+            } # MSVC
+          }, # Release
+        }, # configurations
+    } # target-defaults
 }
diff --git a/src/bindings/bindings.cc b/src/bindings/bindings.cc
index fc9b31e1..f58bb520 100644
--- a/src/bindings/bindings.cc
+++ b/src/bindings/bindings.cc
@@ -1,5 +1,5 @@
 #include "marker-index-wrapper.h"
-#include "nan.h"
+#include <nan.h>
 #include "patch-wrapper.h"
 #include "range-wrapper.h"
 #include "point-wrapper.h"
diff --git a/src/bindings/em/auto-wrap.h b/src/bindings/em/auto-wrap.h
index ff4ff070..7fd3f938 100644
--- a/src/bindings/em/auto-wrap.h
+++ b/src/bindings/em/auto-wrap.h
@@ -7,7 +7,8 @@
 #include <emscripten/val.h>
 #include "flat_set.h"
 #include "marker-index.h"
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include "point.h"
 #include "text.h"
 
diff --git a/src/bindings/marker-index-wrapper.cc b/src/bindings/marker-index-wrapper.cc
index f53853e3..00727f5d 100644
--- a/src/bindings/marker-index-wrapper.cc
+++ b/src/bindings/marker-index-wrapper.cc
@@ -1,9 +1,10 @@
 #include "marker-index-wrapper.h"
 #include <unordered_map>
 #include "marker-index.h"
-#include "nan.h"
+#include <nan.h>
 #include "noop.h"
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include "point-wrapper.h"
 #include "range.h"
 
diff --git a/src/bindings/marker-index-wrapper.h b/src/bindings/marker-index-wrapper.h
index 2f64cc54..0b232e01 100644
--- a/src/bindings/marker-index-wrapper.h
+++ b/src/bindings/marker-index-wrapper.h
@@ -1,6 +1,7 @@
-#include "nan.h"
+#include <nan.h>
 #include "marker-index.h"
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include "range.h"
 
 class MarkerIndexWrapper : public Nan::ObjectWrap {
diff --git a/src/bindings/noop.h b/src/bindings/noop.h
index 6b446a5a..f02917d9 100644
--- a/src/bindings/noop.h
+++ b/src/bindings/noop.h
@@ -1,5 +1,5 @@
 #pragma once
 
-#include "nan.h"
+#include <nan.h>
 
 static void noop(const Nan::FunctionCallbackInfo<v8::Value>&) {}
diff --git a/src/bindings/number-conversion.h b/src/bindings/number-conversion.h
index cc063be9..c0c98b30 100644
--- a/src/bindings/number-conversion.h
+++ b/src/bindings/number-conversion.h
@@ -1,8 +1,9 @@
 #ifndef SUPERSTRING_NUMBER_CONVERSION_H
 #define SUPERSTRING_NUMBER_CONVERSION_H
 
-#include "nan.h"
-#include "optional.h"
+#include <nan.h>
+#include <optional>
+using std::optional;
 
 namespace number_conversion {
   template<typename T>
diff --git a/src/bindings/point-wrapper.cc b/src/bindings/point-wrapper.cc
index 7bd159f7..9d5a0c25 100644
--- a/src/bindings/point-wrapper.cc
+++ b/src/bindings/point-wrapper.cc
@@ -1,6 +1,6 @@
 #include "point-wrapper.h"
 #include <cmath>
-#include "nan.h"
+#include <nan.h>
 
 using namespace v8;
 
diff --git a/src/bindings/point-wrapper.h b/src/bindings/point-wrapper.h
index fc06b263..e380a0b5 100644
--- a/src/bindings/point-wrapper.h
+++ b/src/bindings/point-wrapper.h
@@ -1,8 +1,9 @@
 #ifndef SUPERSTRING_POINT_WRAPPER_H
 #define SUPERSTRING_POINT_WRAPPER_H
 
-#include "nan.h"
-#include "optional.h"
+#include <nan.h>
+#include <optional>
+using std::optional;
 #include "point.h"
 
 class PointWrapper : public Nan::ObjectWrap {
diff --git a/src/bindings/range-wrapper.cc b/src/bindings/range-wrapper.cc
index b0aaf5ab..72a7393b 100644
--- a/src/bindings/range-wrapper.cc
+++ b/src/bindings/range-wrapper.cc
@@ -1,6 +1,6 @@
 #include "range-wrapper.h"
 #include "point-wrapper.h"
-#include "nan.h"
+#include <nan.h>
 
 using namespace v8;
 
diff --git a/src/bindings/range-wrapper.h b/src/bindings/range-wrapper.h
index de08dd59..7755f6fc 100644
--- a/src/bindings/range-wrapper.h
+++ b/src/bindings/range-wrapper.h
@@ -1,8 +1,9 @@
 #ifndef SUPERSTRING_RANGE_WRAPPER_H
 #define SUPERSTRING_RANGE_WRAPPER_H
 
-#include "nan.h"
-#include "optional.h"
+#include <nan.h>
+#include <optional>
+using std::optional;
 #include "point.h"
 #include "range.h"
 
diff --git a/src/bindings/string-conversion.h b/src/bindings/string-conversion.h
index f8178041..abeeeee7 100644
--- a/src/bindings/string-conversion.h
+++ b/src/bindings/string-conversion.h
@@ -2,8 +2,9 @@
 #define SUPERSTRING_STRING_CONVERSION_H
 
 #include <string>
-#include "nan.h"
-#include "optional.h"
+#include <nan.h>
+#include <optional>
+using std::optional;
 #include "text.h"
 
 namespace string_conversion {
diff --git a/src/bindings/text-buffer-snapshot-wrapper.h b/src/bindings/text-buffer-snapshot-wrapper.h
index bb23b4ce..ee2c7298 100644
--- a/src/bindings/text-buffer-snapshot-wrapper.h
+++ b/src/bindings/text-buffer-snapshot-wrapper.h
@@ -1,7 +1,7 @@
 #ifndef SUPERSTRING_TEXT_BUFFER_SNAPSHOT_WRAPPER_H
 #define SUPERSTRING_TEXT_BUFFER_SNAPSHOT_WRAPPER_H
 
-#include "nan.h"
+#include <nan.h>
 #include <string>
 
 // This header can be included by other native node modules, allowing them
diff --git a/src/bindings/text-buffer-wrapper.cc b/src/bindings/text-buffer-wrapper.cc
index 52e7bded..568cc632 100644
--- a/src/bindings/text-buffer-wrapper.cc
+++ b/src/bindings/text-buffer-wrapper.cc
@@ -1,7 +1,7 @@
 #include "text-buffer-wrapper.h"
 #include <sstream>
 #include <iomanip>
-#include <stdio.h>
+#include <cstdio>
 #include "number-conversion.h"
 #include "point-wrapper.h"
 #include "range-wrapper.h"
diff --git a/src/bindings/text-buffer-wrapper.h b/src/bindings/text-buffer-wrapper.h
index ee2261ba..78895456 100644
--- a/src/bindings/text-buffer-wrapper.h
+++ b/src/bindings/text-buffer-wrapper.h
@@ -1,7 +1,7 @@
 #ifndef SUPERSTRING_TEXT_BUFFER_WRAPPER_H
 #define SUPERSTRING_TEXT_BUFFER_WRAPPER_H
 
-#include "nan.h"
+#include <nan.h>
 #include "text-buffer.h"
 #include <unordered_set>
 
diff --git a/src/bindings/text-reader.h b/src/bindings/text-reader.h
index 200b6ce6..7fb6d4b0 100644
--- a/src/bindings/text-reader.h
+++ b/src/bindings/text-reader.h
@@ -1,7 +1,7 @@
 #ifndef SUPERSTRING_TEXT_READER_H
 #define SUPERSTRING_TEXT_READER_H
 
-#include "nan.h"
+#include <nan.h>
 #include "text.h"
 #include "text-buffer.h"
 #include "encoding-conversion.h"
diff --git a/src/bindings/text-writer.h b/src/bindings/text-writer.h
index 97fde24b..9d699e38 100644
--- a/src/bindings/text-writer.h
+++ b/src/bindings/text-writer.h
@@ -1,7 +1,7 @@
 #ifndef SUPERSTRING_TEXT_WRITER_H
 #define SUPERSTRING_TEXT_WRITER_H
 
-#include "nan.h"
+#include <nan.h>
 #include "text.h"
 #include "encoding-conversion.h"
 
diff --git a/src/core/encoding-conversion.cc b/src/core/encoding-conversion.cc
index 7259d40d..424eaaac 100644
--- a/src/core/encoding-conversion.cc
+++ b/src/core/encoding-conversion.cc
@@ -1,7 +1,7 @@
 #include "encoding-conversion.h"
 #include "utf8-conversions.h"
 #include <iconv.h>
-#include <string.h>
+#include <cstring>
 
 using std::function;
 using std::u16string;
diff --git a/src/core/encoding-conversion.h b/src/core/encoding-conversion.h
index 3b91146a..fe667c3d 100644
--- a/src/core/encoding-conversion.h
+++ b/src/core/encoding-conversion.h
@@ -1,9 +1,10 @@
 #ifndef SUPERSTRING_ENCODING_CONVERSION_H_
 #define SUPERSTRING_ENCODING_CONVERSION_H_
 
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include "text.h"
-#include <stdio.h>
+#include <cstdio>
 
 class EncodingConversion {
   void *data;
diff --git a/src/core/libmba-diff.cc b/src/core/libmba-diff.cc
index 418d51a9..7cf09a4d 100644
--- a/src/core/libmba-diff.cc
+++ b/src/core/libmba-diff.cc
@@ -52,9 +52,9 @@
  */
 
 #include "libmba-diff.h"
-#include <stdlib.h>
-#include <limits.h>
-#include <errno.h>
+#include <cstdlib>
+#include <climits>
+#include <cerrno>
 #include <vector>
 
 using std::vector;
diff --git a/src/core/libmba-diff.h b/src/core/libmba-diff.h
index 04237974..72e42c0b 100644
--- a/src/core/libmba-diff.h
+++ b/src/core/libmba-diff.h
@@ -1,7 +1,7 @@
 #ifndef MBA_DIFF_H_
 #define MBA_DIFF_H_
 
-#include <stdint.h>
+#include <cstdint>
 #include <vector>
 
 typedef enum {
diff --git a/src/core/marker-index.cc b/src/core/marker-index.cc
index d622c7ec..b45ccf54 100644
--- a/src/core/marker-index.cc
+++ b/src/core/marker-index.cc
@@ -2,7 +2,7 @@
 #include <climits>
 #include <iterator>
 #include <random>
-#include <stdlib.h>
+#include <cstdlib>
 #include "range.h"
 
 using std::default_random_engine;
diff --git a/src/core/optional.h b/src/core/optional.h
deleted file mode 100644
index 61280d99..00000000
--- a/src/core/optional.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef SUPERSTRING_OPTIONAL_H
-#define SUPERSTRING_OPTIONAL_H
-
-#include <utility>
-
-template <typename T> class optional {
-  T value;
-  bool is_some;
-
-public:
-  optional(T &&value) : value(std::move(value)), is_some(true) {}
-  optional(const T &value) : value(value), is_some(true) {}
-  optional() : value(T()), is_some(false) {}
-
-  T &operator*() { return value; }
-  const T &operator*() const { return value; }
-  const T *operator->() const { return &value; }
-  T *operator->() { return &value; }
-  operator bool() const { return is_some; }
-  bool operator==(const optional<T> &other) {
-    if (is_some) {
-      return other.is_some && value == other.value;
-    } else {
-      return !other.is_some;
-    }
-  }
-};
-
-#endif // SUPERSTRING_OPTIONAL_H
diff --git a/src/core/patch.cc b/src/core/patch.cc
index 8702f9b3..e4d731dd 100644
--- a/src/core/patch.cc
+++ b/src/core/patch.cc
@@ -1,11 +1,12 @@
 #include "patch.h"
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include "text.h"
 #include "text-slice.h"
-#include <assert.h>
+#include <cassert>
 #include <cmath>
 #include <memory>
-#include <stdio.h>
+#include <cstdio>
 #include <sstream>
 #include <vector>
 
diff --git a/src/core/patch.h b/src/core/patch.h
index c59021e5..4ddf8aad 100644
--- a/src/core/patch.h
+++ b/src/core/patch.h
@@ -1,7 +1,8 @@
 #ifndef PATCH_H_
 #define PATCH_H_
 
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include "point.h"
 #include "serializer.h"
 #include "text.h"
diff --git a/src/core/regex.cc b/src/core/regex.cc
index 71629642..c9405d9f 100644
--- a/src/core/regex.cc
+++ b/src/core/regex.cc
@@ -1,6 +1,6 @@
 #include "regex.h"
-#include <stdlib.h>
-#include "pcre2.h"
+#include <cstdlib>
+#include <pcre2.h>
 
 using std::u16string;
 using MatchResult = Regex::MatchResult;
diff --git a/src/core/regex.h b/src/core/regex.h
index 10970306..cd8de961 100644
--- a/src/core/regex.h
+++ b/src/core/regex.h
@@ -1,7 +1,8 @@
 #ifndef REGEX_H_
 #define REGEX_H_
 
-#include "optional.h"
+#include <optional>
+using std::optional;
 #include <string>
 
 struct pcre2_real_code_16;
diff --git a/src/core/text-diff.cc b/src/core/text-diff.cc
index 969b7ea7..e99f2863 100644
--- a/src/core/text-diff.cc
+++ b/src/core/text-diff.cc
@@ -2,7 +2,7 @@
 #include "libmba-diff.h"
 #include "text-slice.h"
 #include <vector>
-#include <string.h>
+#include <cstring>
 #include <ostream>
 #include <cassert>
 
diff --git a/src/core/text-slice.cc b/src/core/text-slice.cc
index 22f298d7..eb9f8615 100644
--- a/src/core/text-slice.cc
+++ b/src/core/text-slice.cc
@@ -1,6 +1,6 @@
 #include "text-slice.h"
 #include "text.h"
-#include <assert.h>
+#include <cassert>
 
 TextSlice::TextSlice() :
   text{nullptr} {}
diff --git a/src/core/text.h b/src/core/text.h
index 0326a902..4f0f9bb5 100644
--- a/src/core/text.h
+++ b/src/core/text.h
@@ -7,7 +7,8 @@
 #include <ostream>
 #include "serializer.h"
 #include "point.h"
-#include "optional.h"
+#include <optional>
+using std::optional;
 
 class TextSlice;