You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by th...@apache.org on 2021/03/07 13:55:26 UTC

[avro] branch master updated: AVRO-3051: Core C++ implementation is modernized (#1106)

This is an automated email from the ASF dual-hosted git repository.

thiru pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new f4e2eba  AVRO-3051: Core C++ implementation is modernized (#1106)
f4e2eba is described below

commit f4e2ebaadaf6e6d99b59882233f8024243adb55d
Author: Thiruvalluvan M G <th...@apache.org>
AuthorDate: Sun Mar 7 19:25:17 2021 +0530

    AVRO-3051: Core C++ implementation is modernized (#1106)
    
    * Core C++ implementation is modernized
    
    * Addressed review comments
    
    * One more review comment addressed
    
    Co-authored-by: Thiruvalluvan M G <th...@startsmartlabs.com>
---
 lang/c++/api/Compiler.hh                       |  14 +-
 lang/c++/api/Config.hh                         |   3 +-
 lang/c++/api/Decoder.hh                        |  33 +-
 lang/c++/api/Encoder.hh                        |  30 +-
 lang/c++/api/Exception.hh                      |  13 +-
 lang/c++/api/Layout.hh                         |  35 +-
 lang/c++/api/LogicalType.hh                    |   6 +-
 lang/c++/api/Node.hh                           |  61 ++--
 lang/c++/api/NodeConcepts.hh                   |  74 ++--
 lang/c++/api/NodeImpl.hh                       | 441 ++++++++++------------
 lang/c++/api/Reader.hh                         |  31 +-
 lang/c++/api/Resolver.hh                       |  21 +-
 lang/c++/api/ResolverSchema.hh                 |  12 +-
 lang/c++/api/Schema.hh                         |  67 ++--
 lang/c++/api/Types.hh                          |  12 +-
 lang/c++/api/ValidSchema.hh                    |   2 +-
 lang/c++/api/Validator.hh                      |  30 +-
 lang/c++/api/Writer.hh                         |  18 +-
 lang/c++/api/Zigzag.hh                         |   1 +
 lang/c++/api/buffer/detail/BufferDetail.hh.rej |  16 +
 lang/c++/impl/BinaryDecoder.cc                 | 144 +++-----
 lang/c++/impl/BinaryEncoder.cc                 | 114 +++---
 lang/c++/impl/Compiler.cc                      | 400 +++++++++-----------
 lang/c++/impl/LogicalType.cc                   |  16 +-
 lang/c++/impl/Node.cc                          | 164 ++++-----
 lang/c++/impl/NodeImpl.cc                      | 488 ++++++++++++-------------
 lang/c++/impl/Schema.cc                        |  76 ++--
 lang/c++/impl/Types.cc                         |  43 +--
 lang/c++/impl/ValidSchema.cc                   | 243 ++++++------
 lang/c++/impl/Validator.cc                     | 163 ++++-----
 lang/c++/impl/Zigzag.cc                        |   1 -
 lang/c++/impl/parsing/JsonCodec.cc             |   4 +-
 lang/c++/test/DataFileTests.cc                 |   6 +-
 lang/c++/test/SchemaTests.cc                   |   5 +
 lang/c++/test/testgentest.cc                   |   4 +-
 35 files changed, 1252 insertions(+), 1539 deletions(-)

diff --git a/lang/c++/api/Compiler.hh b/lang/c++/api/Compiler.hh
index 892d605..a8f0f91 100644
--- a/lang/c++/api/Compiler.hh
+++ b/lang/c++/api/Compiler.hh
@@ -20,7 +20,7 @@
 #define avro_Compiler_hh__
 
 #include "Config.hh"
-#include <stdint.h>
+#include <cstdint>
 #include <istream>
 
 namespace avro {
@@ -46,17 +46,17 @@ AVRO_DECL void compileJsonSchema(std::istream &is, ValidSchema &schema);
 ///
 
 AVRO_DECL bool compileJsonSchema(std::istream &is, ValidSchema &schema,
-    std::string &error);
+                                 std::string &error);
 
-AVRO_DECL ValidSchema compileJsonSchemaFromStream(InputStream& is);
+AVRO_DECL ValidSchema compileJsonSchemaFromStream(InputStream &is);
 
-AVRO_DECL ValidSchema compileJsonSchemaFromMemory(const uint8_t* input, size_t len);
+AVRO_DECL ValidSchema compileJsonSchemaFromMemory(const uint8_t *input, size_t len);
 
-AVRO_DECL ValidSchema compileJsonSchemaFromString(const char* input);
+AVRO_DECL ValidSchema compileJsonSchemaFromString(const char *input);
 
-AVRO_DECL ValidSchema compileJsonSchemaFromString(const std::string& input);
+AVRO_DECL ValidSchema compileJsonSchemaFromString(const std::string &input);
 
-AVRO_DECL ValidSchema compileJsonSchemaFromFile(const char* filename);
+AVRO_DECL ValidSchema compileJsonSchemaFromFile(const char *filename);
 
 } // namespace avro
 
diff --git a/lang/c++/api/Config.hh b/lang/c++/api/Config.hh
index 69d36f2..b69ce73 100644
--- a/lang/c++/api/Config.hh
+++ b/lang/c++/api/Config.hh
@@ -33,8 +33,7 @@
 #endif  // AVRO_DYN_LINK
 
 #include <intsafe.h>
-typedef SSIZE_T ssize_t;
-
+using ssize_t = SSIZE_T;
 #endif  // _WIN32
 
 #ifndef AVRO_DECL
diff --git a/lang/c++/api/Decoder.hh b/lang/c++/api/Decoder.hh
index 5356d79..0cacada 100644
--- a/lang/c++/api/Decoder.hh
+++ b/lang/c++/api/Decoder.hh
@@ -20,7 +20,7 @@
 #define avro_Decoder_hh__
 
 #include "Config.hh"
-#include <stdint.h>
+#include <cstdint>
 #include <string>
 #include <vector>
 #include <memory>
@@ -47,11 +47,11 @@ namespace avro {
  */
 class AVRO_DECL Decoder {
 public:
-    virtual ~Decoder() { };
+    virtual ~Decoder() = default;
     /// All future decoding will come from is, which should be valid
     /// until replaced by another call to init() or this Decoder is
     /// destructed.
-    virtual void init(InputStream& is) = 0;
+    virtual void init(InputStream &is) = 0;
 
     /// Decodes a null from the current stream.
     virtual void decodeNull() = 0;
@@ -81,12 +81,12 @@ public:
     /**
      * Decodes a UTF-8 string from the stream and assigns it to value.
      */
-    virtual void decodeString(std::string& value) = 0;
+    virtual void decodeString(std::string &value) = 0;
 
     /// Skips a string on the current stream.
     virtual void skipString() = 0;
 
-    /// Decodes arbitray binary data from the current stream.
+    /// Decodes arbitrary binary data from the current stream.
     std::vector<uint8_t> decodeBytes() {
         std::vector<uint8_t> result;
         decodeBytes(result);
@@ -95,7 +95,7 @@ public:
 
     /// Decodes arbitrary binary data from the current stream and puts it
     /// in value.
-    virtual void decodeBytes(std::vector<uint8_t>& value) = 0;
+    virtual void decodeBytes(std::vector<uint8_t> &value) = 0;
 
     /// Skips bytes on the current stream.
     virtual void skipBytes() = 0;
@@ -116,9 +116,9 @@ public:
      * Decodes a fixed from the current stream.
      * \param[in] n The size (byte count) of the fixed being read.
      * \param[out] value The value that receives the fixed. The vector will
-     * be size-adjusted based on the fixed's size.
+     * be size-adjusted based on the fixed schema's size.
      */
-    virtual void decodeFixed(size_t n, std::vector<uint8_t>& value) = 0;
+    virtual void decodeFixed(size_t n, std::vector<uint8_t> &value) = 0;
 
     /// Skips fixed length binary on the current stream.
     virtual void skipFixed(size_t n) = 0;
@@ -174,7 +174,7 @@ public:
 /**
  * Shared pointer to Decoder.
  */
-typedef std::shared_ptr<Decoder> DecoderPtr;
+using DecoderPtr = std::shared_ptr<Decoder>;
 
 /**
  * ResolvingDecoder is derived from \ref Decoder, with an additional
@@ -187,13 +187,13 @@ public:
     /// order in the schema because the writer's field order could
     /// be different. In order to avoid buffering and later use,
     /// we return the values in the writer's field order.
-    virtual const std::vector<size_t>& fieldOrder() = 0;
+    virtual const std::vector<size_t> &fieldOrder() = 0;
 };
 
 /**
  * Shared pointer to ResolvingDecoder.
  */
-typedef std::shared_ptr<ResolvingDecoder> ResolvingDecoderPtr;
+using ResolvingDecoderPtr = std::shared_ptr<ResolvingDecoder>;
 /**
  *  Returns an decoder that can decode binary Avro standard.
  */
@@ -203,13 +203,13 @@ AVRO_DECL DecoderPtr binaryDecoder();
  *  Returns an decoder that validates sequence of calls to an underlying
  *  Decoder against the given schema.
  */
-AVRO_DECL DecoderPtr validatingDecoder(const ValidSchema& schema,
-    const DecoderPtr& base);
+AVRO_DECL DecoderPtr validatingDecoder(const ValidSchema &schema,
+                                       const DecoderPtr &base);
 
 /**
  *  Returns an decoder that can decode Avro standard for JSON.
  */
-AVRO_DECL DecoderPtr jsonDecoder(const ValidSchema& schema);
+AVRO_DECL DecoderPtr jsonDecoder(const ValidSchema &schema);
 
 /**
  *  Returns a decoder that decodes avro data from base written according to
@@ -217,9 +217,8 @@ AVRO_DECL DecoderPtr jsonDecoder(const ValidSchema& schema);
  *  The client uses the decoder as if the data were written using readerSchema.
  *  // FIXME: Handle out of order fields.
  */
-AVRO_DECL ResolvingDecoderPtr resolvingDecoder(const ValidSchema& writer,
-    const ValidSchema& reader, const DecoderPtr& base);
-
+AVRO_DECL ResolvingDecoderPtr resolvingDecoder(const ValidSchema &writer,
+                                               const ValidSchema &reader, const DecoderPtr &base);
 
 }   // namespace avro
 
diff --git a/lang/c++/api/Encoder.hh b/lang/c++/api/Encoder.hh
index 7849e93..8e2e41f 100644
--- a/lang/c++/api/Encoder.hh
+++ b/lang/c++/api/Encoder.hh
@@ -20,7 +20,7 @@
 #define avro_Encoder_hh__
 
 #include "Config.hh"
-#include <stdint.h>
+#include <cstdint>
 #include <string>
 #include <vector>
 #include <memory>
@@ -31,7 +31,7 @@
 /// \file
 ///
 /// Low level support for encoding avro values.
-/// This class has two types of funtions.  One type of functions support
+/// This class has two types of functions.  One type of functions support
 /// the writing of leaf values (for example, encodeLong and
 /// encodeString).  These functions have analogs in Decoder.
 ///
@@ -46,16 +46,16 @@ namespace avro {
 
 /**
  * The abstract base class for all Avro encoders. The implementations
- * differ in the method of encoding (binary vresus JSON) or in capabilities
+ * differ in the method of encoding (binary versus JSON) or in capabilities
  * such as ability to verify the order of invocation of different functions.
  */
 class AVRO_DECL Encoder {
 public:
-    virtual ~Encoder() { };
+    virtual ~Encoder() = default;
     /// All future encodings will go to os, which should be valid until
     /// it is reset with another call to init() or the encoder is
     /// destructed.
-    virtual void init(OutputStream& os) = 0;
+    virtual void init(OutputStream &os) = 0;
 
     /// Flushes any data in internal buffers.
     virtual void flush() = 0;
@@ -83,10 +83,10 @@ public:
     virtual void encodeDouble(double d) = 0;
 
     /// Encodes a UTF-8 string to the current stream.
-    virtual void encodeString(const std::string& s) = 0;
+    virtual void encodeString(const std::string &s) = 0;
 
     /**
-     * Encodes aribtray binary data into tthe current stream as Avro "bytes"
+     * Encodes arbitrary binary data into the current stream as Avro "bytes"
      * data type.
      * \param bytes Where the data is
      * \param len Number of bytes at \p bytes.
@@ -94,11 +94,11 @@ public:
     virtual void encodeBytes(const uint8_t *bytes, size_t len) = 0;
 
     /**
-     * Encodes aribtray binary data into tthe current stream as Avro "bytes"
+     * Encodes arbitrary binary data into the current stream as Avro "bytes"
      * data type.
      * \param bytes The data.
      */
-    void encodeBytes(const std::vector<uint8_t>& bytes) {
+    void encodeBytes(const std::vector<uint8_t> &bytes) {
         uint8_t b = 0;
         encodeBytes(bytes.empty() ? &b : bytes.data(), bytes.size());
     }
@@ -111,7 +111,7 @@ public:
      * \param bytes The fixed, the length of which is taken as the size
      * of fixed.
      */
-    void encodeFixed(const std::vector<uint8_t>& bytes) {
+    void encodeFixed(const std::vector<uint8_t> &bytes) {
         encodeFixed(bytes.data(), bytes.size());
     }
 
@@ -144,7 +144,7 @@ public:
 /**
  * Shared pointer to Encoder.
  */
-typedef std::shared_ptr<Encoder> EncoderPtr;
+using EncoderPtr = std::shared_ptr<Encoder>;
 
 /**
  *  Returns an encoder that can encode binary Avro standard.
@@ -155,18 +155,18 @@ AVRO_DECL EncoderPtr binaryEncoder();
  *  Returns an encoder that validates sequence of calls to an underlying
  *  Encoder against the given schema.
  */
-AVRO_DECL EncoderPtr validatingEncoder(const ValidSchema& schema,
-    const EncoderPtr& base);
+AVRO_DECL EncoderPtr validatingEncoder(const ValidSchema &schema,
+                                       const EncoderPtr &base);
 
 /**
  *  Returns an encoder that encodes Avro standard for JSON.
  */
-AVRO_DECL EncoderPtr jsonEncoder(const ValidSchema& schema);
+AVRO_DECL EncoderPtr jsonEncoder(const ValidSchema &schema);
 
 /**
  *  Returns an encoder that encodes Avro standard for pretty printed JSON.
  */
-AVRO_DECL EncoderPtr jsonPrettyEncoder(const ValidSchema& schema);
+AVRO_DECL EncoderPtr jsonPrettyEncoder(const ValidSchema &schema);
 
 }   // namespace avro
 
diff --git a/lang/c++/api/Exception.hh b/lang/c++/api/Exception.hh
index 7c5410f..4ab7323 100644
--- a/lang/c++/api/Exception.hh
+++ b/lang/c++/api/Exception.hh
@@ -28,17 +28,12 @@ namespace avro {
 /// Wrapper for std::runtime_error that provides convenience constructor
 /// for boost::format objects
 
-class AVRO_DECL Exception : public virtual std::runtime_error
-{
-  public:
+class AVRO_DECL Exception : public virtual std::runtime_error {
+public:
 
-    Exception(const std::string &msg) :
-        std::runtime_error(msg)
-    { }
+    explicit Exception(const std::string &msg) : std::runtime_error(msg) {}
 
-    Exception(const boost::format &msg) :
-        std::runtime_error( boost::str(msg))
-    { }
+    explicit Exception(const boost::format &msg) : std::runtime_error(boost::str(msg)) {}
 };
 
 } // namespace avro
diff --git a/lang/c++/api/Layout.hh b/lang/c++/api/Layout.hh
index ffd810c..a71cf3e 100644
--- a/lang/c++/api/Layout.hh
+++ b/lang/c++/api/Layout.hh
@@ -28,52 +28,39 @@
 namespace avro {
 
 class AVRO_DECL Layout : private boost::noncopyable {
+protected:
+    explicit Layout(size_t offset = 0) : offset_(offset) {}
 
-  protected:
-
-    Layout(size_t offset = 0) :
-        offset_(offset)
-    {}
-
-  public:
-
+public:
     size_t offset() const {
         return offset_;
     }
+    virtual ~Layout() = default;
 
-    virtual ~Layout() {}
-
-  private:
-
+private:
     const size_t offset_;
 };
 
 class AVRO_DECL PrimitiveLayout : public Layout {
-
-  public:
-
-    PrimitiveLayout(size_t offset = 0) :
-        Layout(offset)
-    {}
+public:
+    explicit PrimitiveLayout(size_t offset = 0) : Layout(offset) {}
 };
 
 class AVRO_DECL CompoundLayout : public Layout {
 
-  public:
+public:
 
-    CompoundLayout(size_t offset = 0) :
-        Layout(offset)
-    {}
+    explicit CompoundLayout(size_t offset = 0) : Layout(offset) {}
 
     void add(std::unique_ptr<Layout> &layout) {
         layouts_.push_back(std::move(layout));
     }
 
-    const Layout &at (size_t idx) const {
+    const Layout &at(size_t idx) const {
         return *layouts_.at(idx);
     }
 
-  private:
+private:
 
     std::vector<std::unique_ptr<Layout> > layouts_;
 };
diff --git a/lang/c++/api/LogicalType.hh b/lang/c++/api/LogicalType.hh
index 3397278..c21fafb 100644
--- a/lang/c++/api/LogicalType.hh
+++ b/lang/c++/api/LogicalType.hh
@@ -26,7 +26,7 @@
 namespace avro {
 
 class AVRO_DECL LogicalType {
-  public:
+public:
     enum Type {
         NONE,
         DECIMAL,
@@ -52,9 +52,9 @@ class AVRO_DECL LogicalType {
     void setScale(int scale);
     int scale() const { return scale_; }
 
-    void printJson(std::ostream& os) const;
+    void printJson(std::ostream &os) const;
 
-  private:
+private:
     Type type_;
     int precision_;
     int scale_;
diff --git a/lang/c++/api/Node.hh b/lang/c++/api/Node.hh
index 205b06f..45552a3 100644
--- a/lang/c++/api/Node.hh
+++ b/lang/c++/api/Node.hh
@@ -24,6 +24,7 @@
 #include <cassert>
 #include <memory>
 #include <boost/noncopyable.hpp>
+#include <utility>
 
 #include "Exception.hh"
 #include "LogicalType.hh"
@@ -35,39 +36,39 @@ namespace avro {
 class Node;
 class GenericDatum;
 
-typedef std::shared_ptr<Node> NodePtr;
+using NodePtr = std::shared_ptr<Node>;
 
 class AVRO_DECL Name {
     std::string ns_;
     std::string simpleName_;
-public:
-    Name() { }
-    Name(const std::string& fullname);
-    Name(const std::string& simpleName, const std::string& ns) : ns_(ns), simpleName_(simpleName) { check(); }
+ public:
+    Name() = default;
+    explicit Name(const std::string &fullname);
+    Name(std::string simpleName, std::string ns) : ns_(std::move(ns)), simpleName_(std::move(simpleName)) { check(); }
 
-    const std::string fullname() const;
-    const std::string& ns() const { return ns_; }
-    const std::string& simpleName() const { return simpleName_; }
+    std::string fullname() const;
+    const std::string &ns() const { return ns_; }
+    const std::string &simpleName() const { return simpleName_; }
 
-    void ns(const std::string& n) { ns_ = n; }
-    void simpleName(const std::string& n) { simpleName_ = n; }
-    void fullname(const std::string& n);
+    void ns(std::string n) { ns_ = std::move(n); }
+    void simpleName(std::string n) { simpleName_ = std::move(n); }
+    void fullname(const std::string &n);
 
-    bool operator < (const Name& n) const;
+    bool operator<(const Name &n) const;
     void check() const;
-    bool operator == (const Name& n) const;
-    bool operator != (const Name& n) const { return !((*this) == n); }
+    bool operator==(const Name &n) const;
+    bool operator!=(const Name &n) const { return !((*this) == n); }
     void clear() {
         ns_.clear();
         simpleName_.clear();
     }
-    operator std::string() const {
+    explicit operator std::string() const {
         return fullname();
     }
 };
 
 inline
-std::ostream& operator << (std::ostream& os, const Name& n) {
+std::ostream &operator<<(std::ostream &os, const Name &n) {
     return os << n.fullname();
 }
 
@@ -86,15 +87,13 @@ std::ostream& operator << (std::ostream& os, const Name& n) {
 /// different node types.
 ///
 
-class AVRO_DECL Node : private boost::noncopyable
-{
-  public:
+class AVRO_DECL Node : private boost::noncopyable {
+ public:
 
-    Node(Type type) :
+    explicit Node(Type type) :
         type_(type),
         logicalType_(LogicalType::NONE),
-        locked_(false)
-    {}
+        locked_(false) {}
 
     virtual ~Node();
 
@@ -136,14 +135,14 @@ class AVRO_DECL Node : private boost::noncopyable
         doAddLeaf(newLeaf);
     }
     virtual size_t leaves() const = 0;
-    virtual const NodePtr& leafAt(int index) const = 0;
-    virtual const GenericDatum& defaultValueAt(int index) {
+    virtual const NodePtr &leafAt(int index) const = 0;
+    virtual const GenericDatum &defaultValueAt(int index) {
         throw Exception(boost::format("No default value at: %1%") % index);
     }
 
     void addName(const std::string &name) {
         checkLock();
-        checkName(name);
+        checkName(Name(name));
         doAddName(name);
     }
     virtual size_t names() const = 0;
@@ -168,13 +167,13 @@ class AVRO_DECL Node : private boost::noncopyable
 
     // Serialize the default value GenericDatum g for the node contained
     // in a record node.
-    virtual void printDefaultToJson(const GenericDatum& g, std::ostream &os,
+    virtual void printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                     int depth) const = 0;
 
-  protected:
+ protected:
 
     void checkLock() const {
-        if(locked()) {
+        if (locked()) {
             throw Exception("Cannot modify locked schema");
         }
     }
@@ -190,7 +189,7 @@ class AVRO_DECL Node : private boost::noncopyable
     virtual void doAddName(const std::string &name) = 0;
     virtual void doSetFixedSize(int size) = 0;
 
-  private:
+ private:
 
     const Type type_;
     LogicalType logicalType_;
@@ -200,12 +199,10 @@ class AVRO_DECL Node : private boost::noncopyable
 } // namespace avro
 
 namespace std {
-inline std::ostream& operator<<(std::ostream& os, const avro::Node& n)
-{
+inline std::ostream &operator<<(std::ostream &os, const avro::Node &n) {
     n.printJson(os, 0);
     return os;
 }
 }
 
-
 #endif
diff --git a/lang/c++/api/NodeConcepts.hh b/lang/c++/api/NodeConcepts.hh
index c0214ab..3203a94 100644
--- a/lang/c++/api/NodeConcepts.hh
+++ b/lang/c++/api/NodeConcepts.hh
@@ -47,33 +47,29 @@ namespace avro {
 
 namespace concepts {
 
-template <typename Attribute>
-struct NoAttribute
-{
+template<typename Attribute>
+struct NoAttribute {
     static const bool hasAttribute = false;
 
     size_t size() const {
         return 0;
     }
 
-    void add( const Attribute &attr) {
+    void add(const Attribute &/* attr */) {
         // There must be an add function for the generic NodeImpl, but the
         // Node APIs ensure that it is never called, the throw here is
         // just in case
         throw Exception("This type does not have attribute");
     }
 
-    const Attribute &get(size_t index = 0) const {
+    const Attribute &get(size_t /* index */ = 0) const {
         // There must be an get function for the generic NodeImpl, but the
         // Node APIs ensure that it is never called, the throw here is
         // just in case
         throw Exception("This type does not have attribute");
-        // even though this code is unreachable the compiler requires it
-        static const Attribute empty = Attribute();
-        return empty;
     }
 
-    Attribute &get(size_t index = 0) {
+    Attribute &get(size_t /* index */ = 0) {
         // There must be an get function for the generic NodeImpl, but the
         // Node APIs ensure that it is never called, the throw here is
         // just in case
@@ -83,23 +79,19 @@ struct NoAttribute
 };
 
 template<typename Attribute>
-struct SingleAttribute
-{
+struct SingleAttribute {
     static const bool hasAttribute = true;
 
-    SingleAttribute() : attr_()
-    { }
+    SingleAttribute() : attr_() {}
 
-    SingleAttribute(const Attribute& a) : attr_(a) { }
+    explicit SingleAttribute(const Attribute &a) : attr_(a) {}
     // copy constructing from another single attribute is allowed
     SingleAttribute(const SingleAttribute<Attribute> &rhs) :
-        attr_(rhs.attr_)
-    { }
+        attr_(rhs.attr_) {}
 
     // copy constructing from a no attribute is allowed
-    SingleAttribute(const NoAttribute<Attribute> &rhs) :
-        attr_()
-    { }
+    explicit SingleAttribute(const NoAttribute<Attribute> &rhs) :
+        attr_() {}
 
     size_t size() const {
         return 1;
@@ -124,34 +116,30 @@ struct SingleAttribute
     }
 
 private:
-    template<typename T> friend struct MultiAttribute;
+    template<typename T> friend
+    struct MultiAttribute;
     Attribute attr_;
 };
 
 template<typename Attribute>
-struct MultiAttribute
-{
+struct MultiAttribute {
     static const bool hasAttribute = true;
 
-    MultiAttribute()
-    { }
+    MultiAttribute() = default;
 
     // copy constructing from another single attribute is allowed, it
     // pushes the attribute
-    MultiAttribute(const SingleAttribute<Attribute> &rhs)
-    {
+    explicit MultiAttribute(const SingleAttribute<Attribute> &rhs) {
         // since map is the only type that does this we know it's
         // final size will be two, so reserve
         attrs_.reserve(2);
         attrs_.push_back(rhs.attr_);
     }
 
-    MultiAttribute(const MultiAttribute<Attribute> &rhs)  :
-        attrs_(rhs.attrs_)
-    { }
+    MultiAttribute(const MultiAttribute<Attribute> &rhs) :
+        attrs_(rhs.attrs_) {}
 
-    MultiAttribute(const NoAttribute<Attribute> &rhs)
-    {}
+    explicit MultiAttribute(const NoAttribute<Attribute> &rhs) {}
 
     size_t size() const {
         return attrs_.size();
@@ -169,51 +157,47 @@ struct MultiAttribute
         return attrs_.at(index);
     }
 
-  private:
+private:
 
     std::vector<Attribute> attrs_;
 };
 
-
 template<typename T>
 struct NameIndexConcept {
 
     bool lookup(const std::string &name, size_t &index) const {
         throw Exception("Name index does not exist");
-        return 0;
     }
 
-    bool add(const::std::string &name, size_t index) {
+    bool add(const ::std::string &name, size_t) {
         throw Exception("Name index does not exist");
-        return false;
     }
 };
 
 template<>
-struct NameIndexConcept < MultiAttribute<std::string> >
-{
-    typedef std::map<std::string, size_t> IndexMap;
+struct NameIndexConcept<MultiAttribute<std::string> > {
+    using IndexMap = std::map<std::string, size_t>;
 
     bool lookup(const std::string &name, size_t &index) const {
-        IndexMap::const_iterator iter = map_.find(name);
-        if(iter == map_.end()) {
+        auto iter = map_.find(name);
+        if (iter == map_.end()) {
             return false;
         }
         index = iter->second;
         return true;
     }
 
-    bool add(const::std::string &name, size_t index) {
+    bool add(const ::std::string &name, size_t index) {
         bool added = false;
-        IndexMap::iterator lb = map_.lower_bound(name);
-        if(lb == map_.end() || map_.key_comp()(name, lb->first)) {
+        auto lb = map_.lower_bound(name);
+        if (lb == map_.end() || map_.key_comp()(name, lb->first)) {
             map_.insert(lb, IndexMap::value_type(name, index));
             added = true;
         }
         return added;
     }
 
-  private:
+private:
 
     IndexMap map_;
 };
diff --git a/lang/c++/api/NodeImpl.hh b/lang/c++/api/NodeImpl.hh
index debce72..22a7998 100644
--- a/lang/c++/api/NodeImpl.hh
+++ b/lang/c++/api/NodeImpl.hh
@@ -28,6 +28,7 @@
 #include <iostream>
 #include <sstream>
 #include <memory>
+#include <utility>
 
 #include "Node.hh"
 #include "NodeConcepts.hh"
@@ -38,25 +39,23 @@ namespace avro {
 /// whose properties are enabled and disabled by selecting concept classes.
 
 template
-<
-    class NameConcept,
-    class LeavesConcept,
-    class LeafNamesConcept,
-    class SizeConcept
->
-class NodeImpl : public Node
-{
-
-  protected:
-
-    NodeImpl(Type type) :
+    <
+        class NameConcept,
+        class LeavesConcept,
+        class LeafNamesConcept,
+        class SizeConcept
+    >
+class NodeImpl : public Node {
+
+protected:
+
+    explicit NodeImpl(Type type) :
         Node(type),
         nameAttribute_(),
         docAttribute_(),
         leafAttributes_(),
         leafNameAttributes_(),
-        sizeAttribute_()
-    { }
+        sizeAttribute_() {}
 
     NodeImpl(Type type,
              const NameConcept &name,
@@ -68,8 +67,7 @@ class NodeImpl : public Node
         docAttribute_(),
         leafAttributes_(leaves),
         leafNameAttributes_(leafNames),
-        sizeAttribute_(size)
-    { }
+        sizeAttribute_(size) {}
 
     // Ctor with "doc"
     NodeImpl(Type type,
@@ -83,10 +81,9 @@ class NodeImpl : public Node
         docAttribute_(doc),
         leafAttributes_(leaves),
         leafNameAttributes_(leafNames),
-        sizeAttribute_(size)
-    {}
+        sizeAttribute_(size) {}
 
-    void swap(NodeImpl& impl) {
+    void swap(NodeImpl &impl) {
         std::swap(nameAttribute_, impl.nameAttribute_);
         std::swap(docAttribute_, impl.docAttribute_);
         std::swap(leafAttributes_, impl.leafAttributes_);
@@ -95,71 +92,71 @@ class NodeImpl : public Node
         std::swap(nameIndex_, impl.nameIndex_);
     }
 
-    bool hasName() const {
+    bool hasName() const override {
         // e.g.: true for single and multiattributes, false for noattributes.
         return NameConcept::hasAttribute;
     }
 
-    void doSetName(const Name &name) {
+    void doSetName(const Name &name) override {
         nameAttribute_.add(name);
     }
 
-    const Name &name() const {
+    const Name &name() const override {
         return nameAttribute_.get();
     }
 
-    void doSetDoc(const std::string &doc) {
-      docAttribute_.add(doc);
+    void doSetDoc(const std::string &doc) override {
+        docAttribute_.add(doc);
     }
 
-    const std::string &getDoc() const {
-      return docAttribute_.get();
+    const std::string &getDoc() const override {
+        return docAttribute_.get();
     }
 
-    void doAddLeaf(const NodePtr &newLeaf) {
+    void doAddLeaf(const NodePtr &newLeaf) override {
         leafAttributes_.add(newLeaf);
     }
 
-    size_t leaves() const {
+    size_t leaves() const override {
         return leafAttributes_.size();
     }
 
-    const NodePtr &leafAt(int index) const {
+    const NodePtr &leafAt(int index) const override {
         return leafAttributes_.get(index);
     }
 
-    void doAddName(const std::string &name) {
-        if (! nameIndex_.add(name, leafNameAttributes_.size())) {
+    void doAddName(const std::string &name) override {
+        if (!nameIndex_.add(name, leafNameAttributes_.size())) {
             throw Exception(boost::format("Cannot add duplicate name: %1%") % name);
         }
         leafNameAttributes_.add(name);
     }
 
-    size_t names() const {
+    size_t names() const override {
         return leafNameAttributes_.size();
     }
 
-    const std::string &nameAt(int index) const {
+    const std::string &nameAt(int index) const override {
         return leafNameAttributes_.get(index);
     }
 
-    bool nameIndex(const std::string &name, size_t &index) const {
+    bool nameIndex(const std::string &name, size_t &index) const override {
         return nameIndex_.lookup(name, index);
     }
 
-    void doSetFixedSize(int size) {
+    void doSetFixedSize(int size) override {
         sizeAttribute_.add(size);
     }
 
-    int fixedSize() const {
+    int fixedSize() const override {
         return sizeAttribute_.get();
     }
 
-    virtual bool isValid() const = 0;
+    bool isValid() const override = 0;
 
-    void printBasicInfo(std::ostream &os) const;
+    void printBasicInfo(std::ostream &os) const override;
 
-    void setLeafToSymbolic(int index, const NodePtr &node);
+    void setLeafToSymbolic(int index, const NodePtr &node) override;
 
     SchemaResolution furtherResolution(const Node &reader) const {
         SchemaResolution match = RESOLVE_NO_MATCH;
@@ -169,20 +166,19 @@ class NodeImpl : public Node
             // resolve the symbolic type, and check again
             const NodePtr &node = reader.leafAt(0);
             match = resolve(*node);
-        }
-        else if(reader.type() == AVRO_UNION) {
+        } else if (reader.type() == AVRO_UNION) {
 
             // in this case, need to see if there is an exact match for the
             // writer's type, or if not, the first one that can be promoted to a
             // match
 
-            for(size_t i= 0; i < reader.leaves(); ++i)  {
+            for (size_t i = 0; i < reader.leaves(); ++i) {
 
                 const NodePtr &node = reader.leafAt(i);
                 SchemaResolution thisMatch = resolve(*node);
 
                 // if matched then the search is done
-                if(thisMatch == RESOLVE_MATCH) {
+                if (thisMatch == RESOLVE_MATCH) {
                     match = thisMatch;
                     break;
                 }
@@ -209,84 +205,78 @@ class NodeImpl : public Node
     concepts::NameIndexConcept<LeafNamesConcept> nameIndex_;
 };
 
-typedef concepts::NoAttribute<Name>     NoName;
-typedef concepts::SingleAttribute<Name> HasName;
+using NoName = concepts::NoAttribute<Name>;
+using HasName = concepts::SingleAttribute<Name>;
 
-typedef concepts::SingleAttribute<std::string> HasDoc;
+using HasDoc = concepts::SingleAttribute<std::string>;
 
-typedef concepts::NoAttribute<NodePtr>      NoLeaves;
-typedef concepts::SingleAttribute<NodePtr>  SingleLeaf;
-typedef concepts::MultiAttribute<NodePtr>   MultiLeaves;
+using NoLeaves = concepts::NoAttribute<NodePtr>;
+using SingleLeaf = concepts::SingleAttribute<NodePtr>;
+using MultiLeaves = concepts::MultiAttribute<NodePtr>;
 
-typedef concepts::NoAttribute<std::string>     NoLeafNames;
-typedef concepts::MultiAttribute<std::string>  LeafNames;
+using NoLeafNames = concepts::NoAttribute<std::string>;
+using LeafNames = concepts::MultiAttribute<std::string>;
 
-typedef concepts::NoAttribute<int>     NoSize;
-typedef concepts::SingleAttribute<int> HasSize;
+using NoSize = concepts::NoAttribute<int>;
+using HasSize = concepts::SingleAttribute<int>;
 
-typedef NodeImpl< NoName,  NoLeaves,    NoLeafNames,  NoSize  > NodeImplPrimitive;
-typedef NodeImpl< HasName, NoLeaves,    NoLeafNames,  NoSize  > NodeImplSymbolic;
+using NodeImplPrimitive = NodeImpl<NoName, NoLeaves, NoLeafNames, NoSize>;
+using NodeImplSymbolic = NodeImpl<HasName, NoLeaves, NoLeafNames, NoSize>;
 
-typedef NodeImpl< HasName, MultiLeaves, LeafNames,    NoSize  > NodeImplRecord;
-typedef NodeImpl< HasName, NoLeaves,    LeafNames,    NoSize  > NodeImplEnum;
-typedef NodeImpl< NoName,  SingleLeaf,  NoLeafNames,  NoSize  > NodeImplArray;
-typedef NodeImpl< NoName,  MultiLeaves, NoLeafNames,  NoSize  > NodeImplMap;
-typedef NodeImpl< NoName,  MultiLeaves, NoLeafNames,  NoSize  > NodeImplUnion;
-typedef NodeImpl< HasName, NoLeaves,    NoLeafNames,  HasSize > NodeImplFixed;
+using NodeImplRecord = NodeImpl<HasName, MultiLeaves, LeafNames, NoSize>;
+using NodeImplEnum = NodeImpl<HasName, NoLeaves, LeafNames, NoSize>;
+using NodeImplArray = NodeImpl<NoName, SingleLeaf, NoLeafNames, NoSize>;
+using NodeImplMap = NodeImpl<NoName, MultiLeaves, NoLeafNames, NoSize>;
+using NodeImplUnion = NodeImpl<NoName, MultiLeaves, NoLeafNames, NoSize>;
+using NodeImplFixed = NodeImpl<HasName, NoLeaves, NoLeafNames, HasSize>;
 
-class AVRO_DECL NodePrimitive : public NodeImplPrimitive
-{
-  public:
+class AVRO_DECL NodePrimitive : public NodeImplPrimitive {
+public:
 
     explicit NodePrimitive(Type type) :
-        NodeImplPrimitive(type)
-    { }
+        NodeImplPrimitive(type) {}
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return true;
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-class AVRO_DECL NodeSymbolic : public NodeImplSymbolic
-{
-    typedef std::weak_ptr<Node> NodeWeakPtr;
+class AVRO_DECL NodeSymbolic : public NodeImplSymbolic {
+    using NodeWeakPtr = std::weak_ptr<Node>;
 
-  public:
+public:
 
     NodeSymbolic() :
-        NodeImplSymbolic(AVRO_SYMBOLIC)
-    { }
+        NodeImplSymbolic(AVRO_SYMBOLIC) {}
 
     explicit NodeSymbolic(const HasName &name) :
-        NodeImplSymbolic(AVRO_SYMBOLIC, name, NoLeaves(), NoLeafNames(), NoSize())
-    { }
+        NodeImplSymbolic(AVRO_SYMBOLIC, name, NoLeaves(), NoLeafNames(), NoSize()) {}
 
-    NodeSymbolic(const HasName &name, const NodePtr n) :
-        NodeImplSymbolic(AVRO_SYMBOLIC, name, NoLeaves(), NoLeafNames(), NoSize()), actualNode_(n)
-    { }
-    SchemaResolution resolve(const Node &reader)  const;
+    NodeSymbolic(const HasName &name, const NodePtr &n) :
+        NodeImplSymbolic(AVRO_SYMBOLIC, name, NoLeaves(), NoLeafNames(), NoSize()), actualNode_(n) {}
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return (nameAttribute_.size() == 1);
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 
     bool isSet() const {
-         return (actualNode_.lock() != 0);
+        return (actualNode_.lock() != nullptr);
     }
 
     NodePtr getNode() const {
         NodePtr node = actualNode_.lock();
-        if(!node) {
+        if (!node) {
             throw Exception(boost::format("Could not follow symbol %1%") % name());
         }
         return node;
@@ -296,7 +286,7 @@ class AVRO_DECL NodeSymbolic : public NodeImplSymbolic
         actualNode_ = node;
     }
 
-  protected:
+protected:
 
     NodeWeakPtr actualNode_;
 
@@ -305,26 +295,16 @@ class AVRO_DECL NodeSymbolic : public NodeImplSymbolic
 class AVRO_DECL NodeRecord : public NodeImplRecord {
     std::vector<GenericDatum> defaultValues;
 public:
-    NodeRecord() : NodeImplRecord(AVRO_RECORD) { }
+    NodeRecord() : NodeImplRecord(AVRO_RECORD) {}
     NodeRecord(const HasName &name, const MultiLeaves &fields,
-        const LeafNames &fieldsNames,
-        const std::vector<GenericDatum>& dv) :
-        NodeImplRecord(AVRO_RECORD, name, fields, fieldsNames, NoSize()),
-        defaultValues(dv) {
-        for (size_t i = 0; i < leafNameAttributes_.size(); ++i) {
-            if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
-                throw Exception(boost::format(
-                    "Cannot add duplicate field: %1%") %
-                    leafNameAttributes_.get(i));
-            }
-        }
-    }
+               const LeafNames &fieldsNames,
+               std::vector<GenericDatum> dv);
 
     NodeRecord(const HasName &name, const HasDoc &doc, const MultiLeaves &fields,
-        const LeafNames &fieldsNames,
-        const std::vector<GenericDatum> &dv) :
+               const LeafNames &fieldsNames,
+               std::vector<GenericDatum> dv) :
         NodeImplRecord(AVRO_RECORD, name, doc, fields, fieldsNames, NoSize()),
-        defaultValues(dv) {
+        defaultValues(std::move(dv)) {
         for (size_t i = 0; i < leafNameAttributes_.size(); ++i) {
             if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
                 throw Exception(boost::format(
@@ -334,177 +314,150 @@ public:
         }
     }
 
-    void swap(NodeRecord& r) {
+    void swap(NodeRecord &r) {
         NodeImplRecord::swap(r);
         defaultValues.swap(r.defaultValues);
     }
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return ((nameAttribute_.size() == 1) &&
             (leafAttributes_.size() == leafNameAttributes_.size()));
     }
 
-    const GenericDatum& defaultValueAt(int index) {
+    const GenericDatum &defaultValueAt(int index) override {
         return defaultValues[index];
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-class AVRO_DECL NodeEnum : public NodeImplEnum
-{
-  public:
+class AVRO_DECL NodeEnum : public NodeImplEnum {
+public:
 
     NodeEnum() :
-        NodeImplEnum(AVRO_ENUM)
-    { }
+        NodeImplEnum(AVRO_ENUM) {}
 
     NodeEnum(const HasName &name, const LeafNames &symbols) :
-        NodeImplEnum(AVRO_ENUM, name, NoLeaves(), symbols, NoSize())
-    {
-        for(size_t i=0; i < leafNameAttributes_.size(); ++i) {
-            if(!nameIndex_.add(leafNameAttributes_.get(i), i)) {
-                 throw Exception(boost::format("Cannot add duplicate enum: %1%") % leafNameAttributes_.get(i));
+        NodeImplEnum(AVRO_ENUM, name, NoLeaves(), symbols, NoSize()) {
+        for (size_t i = 0; i < leafNameAttributes_.size(); ++i) {
+            if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
+                throw Exception(boost::format("Cannot add duplicate enum: %1%") % leafNameAttributes_.get(i));
             }
         }
     }
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return (
-                (nameAttribute_.size() == 1) &&
+            (nameAttribute_.size() == 1) &&
                 (leafNameAttributes_.size() > 0)
-               );
+        );
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-class AVRO_DECL NodeArray : public NodeImplArray
-{
-  public:
+class AVRO_DECL NodeArray : public NodeImplArray {
+public:
 
     NodeArray() :
-        NodeImplArray(AVRO_ARRAY)
-    { }
+        NodeImplArray(AVRO_ARRAY) {}
 
     explicit NodeArray(const SingleLeaf &items) :
-        NodeImplArray(AVRO_ARRAY, NoName(), items, NoLeafNames(), NoSize())
-    { }
+        NodeImplArray(AVRO_ARRAY, NoName(), items, NoLeafNames(), NoSize()) {}
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return (leafAttributes_.size() == 1);
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-class AVRO_DECL NodeMap : public NodeImplMap
-{
-  public:
+class AVRO_DECL NodeMap : public NodeImplMap {
+public:
 
-    NodeMap() :
-        NodeImplMap(AVRO_MAP)
-    {
-         NodePtr key(new NodePrimitive(AVRO_STRING));
-         doAddLeaf(key);
-    }
+    NodeMap();
 
     explicit NodeMap(const SingleLeaf &values) :
-        NodeImplMap(AVRO_MAP, NoName(), values, NoLeafNames(), NoSize())
-    {
+        NodeImplMap(AVRO_MAP, NoName(), MultiLeaves(values), NoLeafNames(), NoSize()) {
         // need to add the key for the map too
         NodePtr key(new NodePrimitive(AVRO_STRING));
+        // FIXME: Calling virtual member function from constructor
         doAddLeaf(key);
 
         // key goes before value
         std::swap(leafAttributes_.get(0), leafAttributes_.get(1));
     }
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return (leafAttributes_.size() == 2);
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-class AVRO_DECL NodeUnion : public NodeImplUnion
-{
-  public:
+class AVRO_DECL NodeUnion : public NodeImplUnion {
+public:
 
     NodeUnion() :
-        NodeImplUnion(AVRO_UNION)
-    { }
+        NodeImplUnion(AVRO_UNION) {}
 
     explicit NodeUnion(const MultiLeaves &types) :
-        NodeImplUnion(AVRO_UNION, NoName(), types, NoLeafNames(), NoSize())
-    { }
+        NodeImplUnion(AVRO_UNION, NoName(), types, NoLeafNames(), NoSize()) {}
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         std::set<std::string> seen;
         if (leafAttributes_.size() >= 1) {
             for (size_t i = 0; i < leafAttributes_.size(); ++i) {
                 std::string name;
-                const NodePtr& n = leafAttributes_.get(i);
+                const NodePtr &n = leafAttributes_.get(i);
                 switch (n->type()) {
-                case AVRO_STRING:
-                    name = "string";
-                    break;
-                case AVRO_BYTES:
-                    name = "bytes";
-                    break;
-                case AVRO_INT:
-                    name = "int";
-                    break;
-                case AVRO_LONG:
-                    name = "long";
-                    break;
-                case AVRO_FLOAT:
-                    name = "float";
-                    break;
-                case AVRO_DOUBLE:
-                    name = "double";
-                    break;
-                case AVRO_BOOL:
-                    name = "bool";
-                    break;
-                case AVRO_NULL:
-                    name = "null";
-                    break;
-                case AVRO_ARRAY:
-                    name = "array";
-                    break;
-                case AVRO_MAP:
-                    name = "map";
-                    break;
-                case AVRO_RECORD:
-                case AVRO_ENUM:
-                case AVRO_UNION:
-                case AVRO_FIXED:
-                case AVRO_SYMBOLIC:
-                    name = n->name().fullname();
-                    break;
-                default:
-                    return false;
+                    case AVRO_STRING:name = "string";
+                        break;
+                    case AVRO_BYTES:name = "bytes";
+                        break;
+                    case AVRO_INT:name = "int";
+                        break;
+                    case AVRO_LONG:name = "long";
+                        break;
+                    case AVRO_FLOAT:name = "float";
+                        break;
+                    case AVRO_DOUBLE:name = "double";
+                        break;
+                    case AVRO_BOOL:name = "bool";
+                        break;
+                    case AVRO_NULL:name = "null";
+                        break;
+                    case AVRO_ARRAY:name = "array";
+                        break;
+                    case AVRO_MAP:name = "map";
+                        break;
+                    case AVRO_RECORD:
+                    case AVRO_ENUM:
+                    case AVRO_UNION:
+                    case AVRO_FIXED:
+                    case AVRO_SYMBOLIC:name = n->name().fullname();
+                        break;
+                    default:return false;
                 }
                 if (seen.find(name) != seen.end()) {
                     return false;
@@ -516,102 +469,92 @@ class AVRO_DECL NodeUnion : public NodeImplUnion
         return false;
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-class AVRO_DECL NodeFixed : public NodeImplFixed
-{
-  public:
+class AVRO_DECL NodeFixed : public NodeImplFixed {
+public:
 
     NodeFixed() :
-        NodeImplFixed(AVRO_FIXED)
-    { }
+        NodeImplFixed(AVRO_FIXED) {}
 
     NodeFixed(const HasName &name, const HasSize &size) :
-        NodeImplFixed(AVRO_FIXED, name, NoLeaves(), NoLeafNames(), size)
-    { }
+        NodeImplFixed(AVRO_FIXED, name, NoLeaves(), NoLeafNames(), size) {}
 
-    SchemaResolution resolve(const Node &reader)  const;
+    SchemaResolution resolve(const Node &reader) const override;
 
-    void printJson(std::ostream &os, int depth) const;
+    void printJson(std::ostream &os, int depth) const override;
 
-    bool isValid() const {
+    bool isValid() const override {
         return (
-                (nameAttribute_.size() == 1) &&
+            (nameAttribute_.size() == 1) &&
                 (sizeAttribute_.size() == 1)
-               );
+        );
     }
 
-    void printDefaultToJson(const GenericDatum& g, std::ostream &os, int depth) const;
+    void printDefaultToJson(const GenericDatum &g, std::ostream &os, int depth) const override;
 };
 
-template < class A, class B, class C, class D >
+template<class A, class B, class C, class D>
 inline void
-NodeImpl<A,B,C,D>::setLeafToSymbolic(int index, const NodePtr &node)
-{
-    if(!B::hasAttribute) {
+NodeImpl<A, B, C, D>::setLeafToSymbolic(int index, const NodePtr &node) {
+    if (!B::hasAttribute) {
         throw Exception("Cannot change leaf node for nonexistent leaf");
     }
 
-    NodePtr &replaceNode = const_cast<NodePtr &>(leafAttributes_.get(index));
-    if(replaceNode->name() != node->name()) {
+    auto &replaceNode = const_cast<NodePtr &>(leafAttributes_.get(index));
+    if (replaceNode->name() != node->name()) {
         throw Exception("Symbolic name does not match the name of the schema it references");
     }
 
-    NodePtr symbol(new NodeSymbolic);
-    NodeSymbolic *ptr = static_cast<NodeSymbolic *> (symbol.get());
-
-    ptr->setName(node->name());
-    ptr->setNode(node);
-    replaceNode.swap(symbol);
+    auto symbol = std::make_shared<NodeSymbolic>();
+    symbol->setName(node->name());
+    symbol->setNode(node);
+    replaceNode = symbol;
 }
 
-template < class A, class B, class C, class D >
+template<class A, class B, class C, class D>
 inline void
-NodeImpl<A,B,C,D>::printBasicInfo(std::ostream &os) const
-{
+NodeImpl<A, B, C, D>::printBasicInfo(std::ostream &os) const {
     os << type();
-    if(hasName()) {
+    if (hasName()) {
         os << ' ' << nameAttribute_.get();
     }
 
-    if(D::hasAttribute) {
+    if (D::hasAttribute) {
         os << " " << sizeAttribute_.get();
     }
     os << '\n';
     int count = leaves();
     count = count ? count : names();
-    for(int i= 0; i < count; ++i) {
-        if( C::hasAttribute ) {
+    for (int i = 0; i < count; ++i) {
+        if (C::hasAttribute) {
             os << "name " << nameAt(i) << '\n';
         }
-        if( type() != AVRO_SYMBOLIC && leafAttributes_.hasAttribute) {
+        if (type() != AVRO_SYMBOLIC && leafAttributes_.hasAttribute) {
             leafAt(i)->printBasicInfo(os);
         }
     }
-    if(isCompound(type())) {
+    if (isCompound(type())) {
         os << "end " << type() << '\n';
     }
 }
 
-
-inline NodePtr resolveSymbol(const NodePtr &node)
-{
-    if(node->type() != AVRO_SYMBOLIC) {
+inline NodePtr resolveSymbol(const NodePtr &node) {
+    if (node->type() != AVRO_SYMBOLIC) {
         throw Exception("Only symbolic nodes may be resolved");
     }
     std::shared_ptr<NodeSymbolic> symNode = std::static_pointer_cast<NodeSymbolic>(node);
     return symNode->getNode();
 }
 
-template< typename T >
-inline std::string intToHex(T i)
-{
-  std::stringstream stream;
-  stream << "\\u"
-         << std::setfill('0') << std::setw(sizeof(T))
-         << std::hex << i;
-  return stream.str();
+template<typename T>
+inline std::string intToHex(T i) {
+    std::stringstream stream;
+    stream << "\\u"
+           << std::setfill('0') << std::setw(sizeof(T))
+           << std::hex << i;
+    return stream.str();
 }
 
 } // namespace avro
diff --git a/lang/c++/api/Reader.hh b/lang/c++/api/Reader.hh
index 4f514fb..c460147 100644
--- a/lang/c++/api/Reader.hh
+++ b/lang/c++/api/Reader.hh
@@ -19,7 +19,7 @@
 #ifndef avro_Reader_hh__
 #define avro_Reader_hh__
 
-#include <stdint.h>
+#include <cstdint>
 #include <vector>
 #include <array>
 #include <boost/noncopyable.hpp>
@@ -38,19 +38,16 @@ namespace avro {
 ///
 
 template<class ValidatorType>
-class ReaderImpl : private boost::noncopyable
-{
+class ReaderImpl : private boost::noncopyable {
 
-  public:
+public:
 
     explicit ReaderImpl(const InputBuffer &buffer) :
-        reader_(buffer)
-    {}
+        reader_(buffer) {}
 
     ReaderImpl(const ValidSchema &schema, const InputBuffer &buffer) :
         validator_(schema),
-        reader_(buffer)
-    {}
+        reader_(buffer) {}
 
     void readValue(Null &) {
         validator_.checkTypeExpected(AVRO_NULL);
@@ -65,7 +62,7 @@ class ReaderImpl : private boost::noncopyable
 
     void readValue(int32_t &val) {
         validator_.checkTypeExpected(AVRO_INT);
-        uint32_t encoded = static_cast<uint32_t>(readVarInt());
+        auto encoded = static_cast<uint32_t>(readVarInt());
         val = decodeZigzag32(encoded);
     }
 
@@ -97,13 +94,13 @@ class ReaderImpl : private boost::noncopyable
 
     void readValue(std::string &val) {
         validator_.checkTypeExpected(AVRO_STRING);
-        size_t size = static_cast<size_t>(readSize());
+        auto size = static_cast<size_t>(readSize());
         reader_.read(val, size);
     }
 
     void readBytes(std::vector<uint8_t> &val) {
         validator_.checkTypeExpected(AVRO_BYTES);
-        size_t size = static_cast<size_t>(readSize());
+        auto size = static_cast<size_t>(readSize());
         val.resize(size);
         reader_.read(reinterpret_cast<char *>(val.data()), size);
     }
@@ -113,12 +110,12 @@ class ReaderImpl : private boost::noncopyable
         reader_.read(reinterpret_cast<char *>(val), size);
     }
 
-    template <size_t N>
+    template<size_t N>
     void readFixed(uint8_t (&val)[N]) {
         this->readFixed(val, N);
     }
 
-    template <size_t N>
+    template<size_t N>
     void readFixed(std::array<uint8_t, N> &val) {
         this->readFixed(val.data(), N);
     }
@@ -167,7 +164,7 @@ class ReaderImpl : private boost::noncopyable
         return validator_.getNextFieldName(name);
     }
 
-  private:
+private:
 
     uint64_t readVarInt() {
         uint64_t encoded = 0;
@@ -197,12 +194,12 @@ class ReaderImpl : private boost::noncopyable
     }
 
     ValidatorType validator_;
-    BufferReader  reader_;
+    BufferReader reader_;
 
 };
 
-typedef ReaderImpl<NullValidator> Reader;
-typedef ReaderImpl<Validator> ValidatingReader;
+using Reader = ReaderImpl<NullValidator>;
+using ValidatingReader = ReaderImpl<Validator>;
 
 } // namespace avro
 
diff --git a/lang/c++/api/Resolver.hh b/lang/c++/api/Resolver.hh
index a0ffcbe..7fbf4cd 100644
--- a/lang/c++/api/Resolver.hh
+++ b/lang/c++/api/Resolver.hh
@@ -21,7 +21,7 @@
 
 #include <memory>
 #include <boost/noncopyable.hpp>
-#include <stdint.h>
+#include <cstdint>
 
 #include "Config.hh"
 #include "Reader.hh"
@@ -34,23 +34,18 @@ namespace avro {
 class ValidSchema;
 class Layout;
 
-class AVRO_DECL Resolver : private boost::noncopyable
-{
-
-  public:
-
+class AVRO_DECL Resolver : private boost::noncopyable {
+public:
     virtual void parse(Reader &reader, uint8_t *address) const = 0;
-    virtual ~Resolver() {}
+    virtual ~Resolver() = default;
 
 };
 
 std::unique_ptr<Resolver> constructResolver(
-        const ValidSchema &rwriterSchema,
-        const ValidSchema &readerSchema,
-        const Layout &readerLayout
-    );
-
-
+    const ValidSchema &writerSchema,
+    const ValidSchema &readerSchema,
+    const Layout &readerLayout
+);
 
 } // namespace avro
 
diff --git a/lang/c++/api/ResolverSchema.hh b/lang/c++/api/ResolverSchema.hh
index 9048a22..d641d08 100644
--- a/lang/c++/api/ResolverSchema.hh
+++ b/lang/c++/api/ResolverSchema.hh
@@ -20,7 +20,7 @@
 #define avro_ResolverSchema_hh__
 
 #include <boost/noncopyable.hpp>
-#include <stdint.h>
+#include <cstdint>
 #include <memory>
 
 #include "Config.hh"
@@ -36,19 +36,13 @@ class Layout;
 class Resolver;
 
 class AVRO_DECL ResolverSchema {
-
-  public:
-
+public:
     ResolverSchema(const ValidSchema &writer, const ValidSchema &reader, const Layout &readerLayout);
 
-  private:
-
+private:
     friend class ResolvingReader;
-
     void parse(Reader &reader, uint8_t *address);
-
     std::shared_ptr<Resolver> resolver_;
-
 };
 
 } // namespace avro
diff --git a/lang/c++/api/Schema.hh b/lang/c++/api/Schema.hh
index b8ad92c..41cf882 100644
--- a/lang/c++/api/Schema.hh
+++ b/lang/c++/api/Schema.hh
@@ -35,9 +35,9 @@ namespace avro {
 /// The root Schema object is a base class.  Nobody constructs this class directly.
 
 class AVRO_DECL Schema {
-public:
+ public:
 
-    virtual ~Schema();
+    virtual ~Schema() = default;
 
     Type type() const {
         return node_->type();
@@ -51,57 +51,56 @@ public:
         return node_;
     }
 
-  protected:
-    Schema();
-    explicit Schema(const NodePtr &node);
-    explicit Schema(Node *node);
+ protected:
+    explicit Schema(NodePtr node) : node_(std::move(node)) {}
+    explicit Schema(Node *node) : node_(node) {}
 
     NodePtr node_;
 };
 
 class AVRO_DECL NullSchema : public Schema {
-public:
-    NullSchema(): Schema(new NodePrimitive(AVRO_NULL)) {}
+ public:
+    NullSchema() : Schema(new NodePrimitive(AVRO_NULL)) {}
 };
 
 class AVRO_DECL BoolSchema : public Schema {
-public:
-    BoolSchema(): Schema(new NodePrimitive(AVRO_BOOL)) {}
+ public:
+    BoolSchema() : Schema(new NodePrimitive(AVRO_BOOL)) {}
 };
 
 class AVRO_DECL IntSchema : public Schema {
-public:
-    IntSchema(): Schema(new NodePrimitive(AVRO_INT)) {}
+ public:
+    IntSchema() : Schema(new NodePrimitive(AVRO_INT)) {}
 };
 
 class AVRO_DECL LongSchema : public Schema {
-public:
-    LongSchema(): Schema(new NodePrimitive(AVRO_LONG)) {}
+ public:
+    LongSchema() : Schema(new NodePrimitive(AVRO_LONG)) {}
 };
 
 class AVRO_DECL FloatSchema : public Schema {
-public:
-    FloatSchema(): Schema(new NodePrimitive(AVRO_FLOAT)) {}
+ public:
+    FloatSchema() : Schema(new NodePrimitive(AVRO_FLOAT)) {}
 };
 
 class AVRO_DECL DoubleSchema : public Schema {
-public:
-    DoubleSchema(): Schema(new NodePrimitive(AVRO_DOUBLE)) {}
+ public:
+    DoubleSchema() : Schema(new NodePrimitive(AVRO_DOUBLE)) {}
 };
 
 class AVRO_DECL StringSchema : public Schema {
-public:
-    StringSchema(): Schema(new NodePrimitive(AVRO_STRING)) {}
+ public:
+    StringSchema() : Schema(new NodePrimitive(AVRO_STRING)) {}
 };
 
 class AVRO_DECL BytesSchema : public Schema {
-public:
-    BytesSchema(): Schema(new NodePrimitive(AVRO_BYTES)) {}
+ public:
+    BytesSchema() : Schema(new NodePrimitive(AVRO_BYTES)) {}
 };
 
 class AVRO_DECL RecordSchema : public Schema {
-public:
-    RecordSchema(const std::string &name);
+ public:
+    explicit RecordSchema(const std::string &name);
     void addField(const std::string &name, const Schema &fieldSchema);
 
     std::string getDoc() const;
@@ -109,37 +108,37 @@ public:
 };
 
 class AVRO_DECL EnumSchema : public Schema {
-public:
-    EnumSchema(const std::string &name);
+ public:
+    explicit EnumSchema(const std::string &name);
     void addSymbol(const std::string &symbol);
 };
 
 class AVRO_DECL ArraySchema : public Schema {
-public:
-    ArraySchema(const Schema &itemsSchema);
+ public:
+    explicit ArraySchema(const Schema &itemsSchema);
     ArraySchema(const ArraySchema &itemsSchema);
 };
 
 class AVRO_DECL MapSchema : public Schema {
-public:
-    MapSchema(const Schema &valuesSchema);
+ public:
+    explicit MapSchema(const Schema &valuesSchema);
     MapSchema(const MapSchema &itemsSchema);
 };
 
 class AVRO_DECL UnionSchema : public Schema {
-public:
+ public:
     UnionSchema();
     void addType(const Schema &typeSchema);
 };
 
 class AVRO_DECL FixedSchema : public Schema {
-public:
+ public:
     FixedSchema(int size, const std::string &name);
 };
 
 class AVRO_DECL SymbolicSchema : public Schema {
-public:
-    SymbolicSchema(const Name& name, const NodePtr& link);
+ public:
+    SymbolicSchema(const Name &name, const NodePtr &link);
 };
 } // namespace avro
 
diff --git a/lang/c++/api/Types.hh b/lang/c++/api/Types.hh
index f42399e..389f24a 100644
--- a/lang/c++/api/Types.hh
+++ b/lang/c++/api/Types.hh
@@ -60,7 +60,7 @@ enum Type {
  * Primitive types are: string, bytes, int, long, float, double, boolean
  * and null
  */
-inline bool isPrimitive(Type t) {
+inline constexpr bool isPrimitive(Type t) noexcept {
     return (t >= AVRO_STRING) && (t < AVRO_RECORD);
 }
 
@@ -69,14 +69,14 @@ inline bool isPrimitive(Type t) {
  * Primitive types are: string, bytes, int, long, float, double, boolean
  * and null
  */
-inline bool isCompound(Type t) {
+inline constexpr bool isCompound(Type t) noexcept {
     return (t>= AVRO_RECORD) && (t < AVRO_NUM_TYPES);
 }
 
 /**
  * Returns true if and only if the given type is a valid avro type.
  */
-inline bool isAvroType(Type t) {
+inline constexpr bool isAvroType(Type t) noexcept {
     return (t >= AVRO_STRING) && (t < AVRO_NUM_TYPES);
 }
 
@@ -84,21 +84,21 @@ inline bool isAvroType(Type t) {
  * Returns true if and only if the given type is within the valid range
  * of enumeration.
  */
-inline bool isAvroTypeOrPseudoType(Type t) {
+inline constexpr bool isAvroTypeOrPseudoType(Type t) noexcept {
     return (t >= AVRO_STRING) && (t <= AVRO_NUM_TYPES);
 }
 
 /**
  * Converts the given type into a string. Useful for generating messages.
  */
-AVRO_DECL const std::string& toString(Type type);
+AVRO_DECL const std::string& toString(Type type) noexcept;
 
 /**
  * Writes a string form of the given type into the given ostream.
  */
 AVRO_DECL std::ostream &operator<< (std::ostream &os, avro::Type type);
 
-/// define a type to identify Null in template functions
+/// define a type to represent Avro Null in template functions
 struct AVRO_DECL Null { };
 
 /**
diff --git a/lang/c++/api/ValidSchema.hh b/lang/c++/api/ValidSchema.hh
index 7b0ec28..f4ea4ed 100644
--- a/lang/c++/api/ValidSchema.hh
+++ b/lang/c++/api/ValidSchema.hh
@@ -39,7 +39,7 @@ class AVRO_DECL Schema;
 
 class AVRO_DECL ValidSchema {
 public:
-    explicit ValidSchema(const NodePtr &root);
+    explicit ValidSchema(NodePtr root);
     explicit ValidSchema(const Schema &schema);
     ValidSchema();
 
diff --git a/lang/c++/api/Validator.hh b/lang/c++/api/Validator.hh
index 2d18053..1bc67ae 100644
--- a/lang/c++/api/Validator.hh
+++ b/lang/c++/api/Validator.hh
@@ -29,9 +29,8 @@
 
 namespace avro {
 
-class AVRO_DECL NullValidator : private boost::noncopyable
-{
-  public:
+class AVRO_DECL NullValidator : private boost::noncopyable {
+public:
 
     explicit NullValidator(const ValidSchema &schema) {}
     NullValidator() {}
@@ -58,9 +57,8 @@ class AVRO_DECL NullValidator : private boost::noncopyable
         return true;
     }
 
-    void checkTypeExpected(Type type) { }
-    void checkFixedSizeExpected(int size) { }
-
+    void checkTypeExpected(Type type) {}
+    void checkFixedSizeExpected(int size) {}
 
 };
 
@@ -70,11 +68,10 @@ class AVRO_DECL NullValidator : private boost::noncopyable
 /// through all leaf nodes but a union only skips to one), and reports which
 /// type is next.
 
-class AVRO_DECL Validator : private boost::noncopyable
-{
-  public:
+class AVRO_DECL Validator : private boost::noncopyable {
+public:
 
-    explicit Validator(const ValidSchema &schema);
+    explicit Validator(ValidSchema schema);
 
     void setCount(int64_t val);
 
@@ -92,7 +89,7 @@ class AVRO_DECL Validator : private boost::noncopyable
     bool getNextFieldName(std::string &name) const;
 
     void checkTypeExpected(Type type) {
-        if(! typeIsExpected(type)) {
+        if (!typeIsExpected(type)) {
             throw Exception(
                 boost::format("Type %1% does not match schema %2%")
                     % type % nextType_
@@ -102,7 +99,7 @@ class AVRO_DECL Validator : private boost::noncopyable
     }
 
     void checkFixedSizeExpected(int size) {
-        if( nextSizeExpected() != size) {
+        if (nextSizeExpected() != size) {
             throw Exception(
                 boost::format("Wrong size for fixed, got %1%, expected %2%")
                     % size % nextSizeExpected()
@@ -111,9 +108,9 @@ class AVRO_DECL Validator : private boost::noncopyable
         checkTypeExpected(AVRO_FIXED);
     }
 
-  private:
+private:
 
-    typedef uint32_t flag_t;
+    using flag_t = uint32_t;
 
     flag_t typeToFlag(Type type) const {
         flag_t flag = (1L << type);
@@ -145,10 +142,9 @@ class AVRO_DECL Validator : private boost::noncopyable
 
     struct CompoundType {
         explicit CompoundType(const NodePtr &n) :
-            node(n), pos(0)
-        {}
+            node(n), pos(0) {}
         NodePtr node;  ///< save the node
-        size_t  pos;   ///< track the leaf position to visit
+        size_t pos;   ///< track the leaf position to visit
     };
 
     std::vector<CompoundType> compoundStack_;
diff --git a/lang/c++/api/Writer.hh b/lang/c++/api/Writer.hh
index 74b057c..b6dca5f 100644
--- a/lang/c++/api/Writer.hh
+++ b/lang/c++/api/Writer.hh
@@ -33,16 +33,14 @@ namespace avro {
 /// Class for writing avro data to a stream.
 
 template<class ValidatorType>
-class WriterImpl : private boost::noncopyable
-{
+class WriterImpl : private boost::noncopyable {
 
-  public:
+public:
 
     WriterImpl() {}
 
     explicit WriterImpl(const ValidSchema &schema) :
-        validator_(schema)
-    {}
+        validator_(schema) {}
 
     void writeValue(const Null &) {
         validator_.checkTypeExpected(AVRO_NULL);
@@ -98,13 +96,13 @@ class WriterImpl : private boost::noncopyable
         putBytes(val, size);
     }
 
-    template <size_t N>
+    template<size_t N>
     void writeFixed(const uint8_t (&val)[N]) {
         validator_.checkFixedSizeExpected(N);
         buffer_.writeTo(reinterpret_cast<const char *>(val), N);
     }
 
-    template <size_t N>
+    template<size_t N>
     void writeFixed(const std::array<uint8_t, N> &val) {
         validator_.checkFixedSizeExpected(val.size());
         buffer_.writeTo(reinterpret_cast<const char *>(val.data()), val.size());
@@ -154,7 +152,7 @@ class WriterImpl : private boost::noncopyable
         return buffer_;
     }
 
-  private:
+private:
 
     void putLong(int64_t val) {
         std::array<uint8_t, 10> bytes;
@@ -178,8 +176,8 @@ class WriterImpl : private boost::noncopyable
 
 };
 
-typedef WriterImpl<NullValidator> Writer;
-typedef WriterImpl<Validator> ValidatingWriter;
+using Writer = WriterImpl<NullValidator>;
+using ValidatingWriter = WriterImpl<Validator>;
 
 } // namespace avro
 
diff --git a/lang/c++/api/Zigzag.hh b/lang/c++/api/Zigzag.hh
index 201a2ad..a6ecf3d 100644
--- a/lang/c++/api/Zigzag.hh
+++ b/lang/c++/api/Zigzag.hh
@@ -48,6 +48,7 @@ AVRO_DECL constexpr int32_t decodeZigzag32(uint32_t input) noexcept {
 AVRO_DECL size_t encodeInt32(int32_t input, std::array<uint8_t, 5> &output) noexcept;
 AVRO_DECL size_t encodeInt64(int64_t input, std::array<uint8_t, 10> &output) noexcept;
 
+
 } // namespace avro
 
 #endif
diff --git a/lang/c++/api/buffer/detail/BufferDetail.hh.rej b/lang/c++/api/buffer/detail/BufferDetail.hh.rej
new file mode 100644
index 0000000..15d261c
--- /dev/null
+++ b/lang/c++/api/buffer/detail/BufferDetail.hh.rej
@@ -0,0 +1,16 @@
+***************
+*** 301,306 ****
+  
+      /// Copy constructor, gets a copy of all the chunks with data.
+      explicit BufferImpl(const BufferImpl &src) :
+          readChunks_(src.readChunks_),
+          freeSpace_(0),
+          size_(src.size_)
+--- 301,307 ----
+  
+      /// Copy constructor, gets a copy of all the chunks with data.
+      explicit BufferImpl(const BufferImpl &src) :
++         boost::noncopyable(),
+          readChunks_(src.readChunks_),
+          freeSpace_(0),
+          size_(src.size_)
diff --git a/lang/c++/impl/BinaryDecoder.cc b/lang/c++/impl/BinaryDecoder.cc
index 71cbf9f..11371f4 100644
--- a/lang/c++/impl/BinaryDecoder.cc
+++ b/lang/c++/impl/BinaryDecoder.cc
@@ -16,8 +16,6 @@
  * limitations under the License.
  */
 
-#define __STDC_LIMIT_MACROS
-
 #include <memory>
 #include "Decoder.hh"
 #include "Zigzag.hh"
@@ -29,66 +27,58 @@ using std::make_shared;
 
 class BinaryDecoder : public Decoder {
     StreamReader in_;
-    const uint8_t* next_;
-    const uint8_t* end_;
-
-    void init(InputStream& ib);
-    void decodeNull();
-    bool decodeBool();
-    int32_t decodeInt();
-    int64_t decodeLong();
-    float decodeFloat();
-    double decodeDouble();
-    void decodeString(std::string& value);
-    void skipString();
-    void decodeBytes(std::vector<uint8_t>& value);
-    void skipBytes();
-    void decodeFixed(size_t n, std::vector<uint8_t>& value);
-    void skipFixed(size_t n);
-    size_t decodeEnum();
-    size_t arrayStart();
-    size_t arrayNext();
-    size_t skipArray();
-    size_t mapStart();
-    size_t mapNext();
-    size_t skipMap();
-    size_t decodeUnionIndex();
+
+    void init(InputStream &is) override;
+    void decodeNull() override;
+    bool decodeBool() override;
+    int32_t decodeInt() override;
+    int64_t decodeLong() override;
+    float decodeFloat() override;
+    double decodeDouble() override;
+    void decodeString(std::string &value) override;
+    void skipString() override;
+    void decodeBytes(std::vector<uint8_t> &value) override;
+    void skipBytes() override;
+    void decodeFixed(size_t n, std::vector<uint8_t> &value) override;
+    void skipFixed(size_t n) override;
+    size_t decodeEnum() override;
+    size_t arrayStart() override;
+    size_t arrayNext() override;
+    size_t skipArray() override;
+    size_t mapStart() override;
+    size_t mapNext() override;
+    size_t skipMap() override;
+    size_t decodeUnionIndex() override;
 
     int64_t doDecodeLong();
     size_t doDecodeItemCount();
     size_t doDecodeLength();
-    void drain();
-    void more();
+    void drain() override;
 };
 
-DecoderPtr binaryDecoder()
-{
+DecoderPtr binaryDecoder() {
     return make_shared<BinaryDecoder>();
 }
 
-void BinaryDecoder::init(InputStream& is)
-{
+void BinaryDecoder::init(InputStream &is) {
     in_.reset(is);
 }
 
-void BinaryDecoder::decodeNull()
-{
+void BinaryDecoder::decodeNull() {
 }
 
-bool BinaryDecoder::decodeBool()
-{
-    uint8_t v = in_.read();
+bool BinaryDecoder::decodeBool() {
+    auto v = in_.read();
     if (v == 0) {
         return false;
     } else if (v == 1) {
         return true;
     }
-    throw Exception("Invalid value for bool");
+    throw Exception(boost::format("Invalid value for bool: %1%") % v);
 }
 
-int32_t BinaryDecoder::decodeInt()
-{
-    int64_t val = doDecodeLong();
+int32_t BinaryDecoder::decodeInt() {
+    auto val = doDecodeLong();
     if (val < INT32_MIN || val > INT32_MAX) {
         throw Exception(
             boost::format("Value out of range for Avro int: %1%") % val);
@@ -96,27 +86,23 @@ int32_t BinaryDecoder::decodeInt()
     return static_cast<int32_t>(val);
 }
 
-int64_t BinaryDecoder::decodeLong()
-{
+int64_t BinaryDecoder::decodeLong() {
     return doDecodeLong();
 }
 
-float BinaryDecoder::decodeFloat()
-{
+float BinaryDecoder::decodeFloat() {
     float result;
     in_.readBytes(reinterpret_cast<uint8_t *>(&result), sizeof(float));
     return result;
 }
 
-double BinaryDecoder::decodeDouble()
-{
+double BinaryDecoder::decodeDouble() {
     double result;
     in_.readBytes(reinterpret_cast<uint8_t *>(&result), sizeof(double));
     return result;
 }
 
-size_t BinaryDecoder::doDecodeLength()
-{
+size_t BinaryDecoder::doDecodeLength() {
     ssize_t len = decodeInt();
     if (len < 0) {
         throw Exception(
@@ -125,29 +111,25 @@ size_t BinaryDecoder::doDecodeLength()
     return len;
 }
 
-void BinaryDecoder::drain()
-{
+void BinaryDecoder::drain() {
     in_.drain(false);
 }
 
-void BinaryDecoder::decodeString(std::string& value)
-{
+void BinaryDecoder::decodeString(std::string &value) {
     size_t len = doDecodeLength();
     value.resize(len);
     if (len > 0) {
-        in_.readBytes(const_cast<uint8_t*>(
-                    reinterpret_cast<const uint8_t*>(value.c_str())), len);
+        in_.readBytes(const_cast<uint8_t *>(
+                          reinterpret_cast<const uint8_t *>(value.c_str())), len);
     }
 }
 
-void BinaryDecoder::skipString()
-{
+void BinaryDecoder::skipString() {
     size_t len = doDecodeLength();
     in_.skipBytes(len);
 }
 
-void BinaryDecoder::decodeBytes(std::vector<uint8_t>& value)
-{
+void BinaryDecoder::decodeBytes(std::vector<uint8_t> &value) {
     size_t len = doDecodeLength();
     value.resize(len);
     if (len > 0) {
@@ -155,38 +137,32 @@ void BinaryDecoder::decodeBytes(std::vector<uint8_t>& value)
     }
 }
 
-void BinaryDecoder::skipBytes()
-{
+void BinaryDecoder::skipBytes() {
     size_t len = doDecodeLength();
     in_.skipBytes(len);
 }
 
-void BinaryDecoder::decodeFixed(size_t n, std::vector<uint8_t>& value)
-{
+void BinaryDecoder::decodeFixed(size_t n, std::vector<uint8_t> &value) {
     value.resize(n);
     if (n > 0) {
         in_.readBytes(value.data(), n);
     }
 }
 
-void BinaryDecoder::skipFixed(size_t n)
-{
+void BinaryDecoder::skipFixed(size_t n) {
     in_.skipBytes(n);
 }
 
-size_t BinaryDecoder::decodeEnum()
-{
+size_t BinaryDecoder::decodeEnum() {
     return static_cast<size_t>(doDecodeLong());
 }
 
-size_t BinaryDecoder::arrayStart()
-{
+size_t BinaryDecoder::arrayStart() {
     return doDecodeItemCount();
 }
 
-size_t BinaryDecoder::doDecodeItemCount()
-{
-    int64_t result = doDecodeLong();
+size_t BinaryDecoder::doDecodeItemCount() {
+    auto result = doDecodeLong();
     if (result < 0) {
         doDecodeLong();
         return static_cast<size_t>(-result);
@@ -194,17 +170,15 @@ size_t BinaryDecoder::doDecodeItemCount()
     return static_cast<size_t>(result);
 }
 
-size_t BinaryDecoder::arrayNext()
-{
+size_t BinaryDecoder::arrayNext() {
     return static_cast<size_t>(doDecodeLong());
 }
 
-size_t BinaryDecoder::skipArray()
-{
-    for (; ;) {
-        int64_t r = doDecodeLong();
+size_t BinaryDecoder::skipArray() {
+    for (;;) {
+        auto r = doDecodeLong();
         if (r < 0) {
-            size_t n = static_cast<size_t>(doDecodeLong());
+            auto n = static_cast<size_t>(doDecodeLong());
             in_.skipBytes(n);
         } else {
             return static_cast<size_t>(r);
@@ -212,23 +186,19 @@ size_t BinaryDecoder::skipArray()
     }
 }
 
-size_t BinaryDecoder::mapStart()
-{
+size_t BinaryDecoder::mapStart() {
     return doDecodeItemCount();
 }
 
-size_t BinaryDecoder::mapNext()
-{
+size_t BinaryDecoder::mapNext() {
     return doDecodeItemCount();
 }
 
-size_t BinaryDecoder::skipMap()
-{
+size_t BinaryDecoder::skipMap() {
     return skipArray();
 }
 
-size_t BinaryDecoder::decodeUnionIndex()
-{
+size_t BinaryDecoder::decodeUnionIndex() {
     return static_cast<size_t>(doDecodeLong());
 }
 
diff --git a/lang/c++/impl/BinaryEncoder.cc b/lang/c++/impl/BinaryEncoder.cc
index 5ceb872..5894cb1 100644
--- a/lang/c++/impl/BinaryEncoder.cc
+++ b/lang/c++/impl/BinaryEncoder.cc
@@ -27,130 +27,110 @@ using std::make_shared;
 class BinaryEncoder : public Encoder {
     StreamWriter out_;
 
-    void init(OutputStream& os);
-    void flush();
-    int64_t byteCount() const;
-    void encodeNull();
-    void encodeBool(bool b);
-    void encodeInt(int32_t i);
-    void encodeLong(int64_t l);
-    void encodeFloat(float f);
-    void encodeDouble(double d);
-    void encodeString(const std::string& s);
-    void encodeBytes(const uint8_t *bytes, size_t len);
-    void encodeFixed(const uint8_t *bytes, size_t len);
-    void encodeEnum(size_t e);
-    void arrayStart();
-    void arrayEnd();
-    void mapStart();
-    void mapEnd();
-    void setItemCount(size_t count);
-    void startItem();
-    void encodeUnionIndex(size_t e);
+    void init(OutputStream &os) override;
+    void flush() override;
+    int64_t byteCount() const override;
+    void encodeNull() override;
+    void encodeBool(bool b) override;
+    void encodeInt(int32_t i) override;
+    void encodeLong(int64_t l) override;
+    void encodeFloat(float f) override;
+    void encodeDouble(double d) override;
+    void encodeString(const std::string &s) override;
+    void encodeBytes(const uint8_t *bytes, size_t len) override;
+    void encodeFixed(const uint8_t *bytes, size_t len) override;
+    void encodeEnum(size_t e) override;
+    void arrayStart() override;
+    void arrayEnd() override;
+    void mapStart() override;
+    void mapEnd() override;
+    void setItemCount(size_t count) override;
+    void startItem() override;
+    void encodeUnionIndex(size_t e) override;
 
     void doEncodeLong(int64_t l);
 };
 
-EncoderPtr binaryEncoder()
-{
+EncoderPtr binaryEncoder() {
     return make_shared<BinaryEncoder>();
 }
 
-void BinaryEncoder::init(OutputStream& os)
-{
+void BinaryEncoder::init(OutputStream &os) {
     out_.reset(os);
 }
 
-void BinaryEncoder::flush()
-{
+void BinaryEncoder::flush() {
     out_.flush();
 }
 
-void BinaryEncoder::encodeNull()
-{
+void BinaryEncoder::encodeNull() {
 }
 
-void BinaryEncoder::encodeBool(bool b)
-{
+void BinaryEncoder::encodeBool(bool b) {
     out_.write(b ? 1 : 0);
 }
 
-void BinaryEncoder::encodeInt(int32_t i)
-{
+void BinaryEncoder::encodeInt(int32_t i) {
     doEncodeLong(i);
 }
 
-void BinaryEncoder::encodeLong(int64_t l)
-{
+void BinaryEncoder::encodeLong(int64_t l) {
     doEncodeLong(l);
 }
 
-void BinaryEncoder::encodeFloat(float f)
-{
-    const uint8_t* p = reinterpret_cast<const uint8_t*>(&f);
+void BinaryEncoder::encodeFloat(float f) {
+    const auto *p = reinterpret_cast<const uint8_t *>(&f);
     out_.writeBytes(p, sizeof(float));
 }
 
-void BinaryEncoder::encodeDouble(double d)
-{
-    const uint8_t* p = reinterpret_cast<const uint8_t*>(&d);
+void BinaryEncoder::encodeDouble(double d) {
+    const auto *p = reinterpret_cast<const uint8_t *>(&d);
     out_.writeBytes(p, sizeof(double));
 }
 
-void BinaryEncoder::encodeString(const std::string& s)
-{
+void BinaryEncoder::encodeString(const std::string &s) {
     doEncodeLong(s.size());
-    out_.writeBytes(reinterpret_cast<const uint8_t*>(s.c_str()), s.size());
+    out_.writeBytes(reinterpret_cast<const uint8_t *>(s.c_str()), s.size());
 }
 
-void BinaryEncoder::encodeBytes(const uint8_t *bytes, size_t len)
-{
+void BinaryEncoder::encodeBytes(const uint8_t *bytes, size_t len) {
     doEncodeLong(len);
     out_.writeBytes(bytes, len);
 }
 
-void BinaryEncoder::encodeFixed(const uint8_t *bytes, size_t len)
-{
+void BinaryEncoder::encodeFixed(const uint8_t *bytes, size_t len) {
     out_.writeBytes(bytes, len);
 }
 
-void BinaryEncoder::encodeEnum(size_t e)
-{
+void BinaryEncoder::encodeEnum(size_t e) {
     doEncodeLong(e);
 }
 
-void BinaryEncoder::arrayStart()
-{
+void BinaryEncoder::arrayStart() {
 }
 
-void BinaryEncoder::arrayEnd()
-{
+void BinaryEncoder::arrayEnd() {
     doEncodeLong(0);
 }
 
-void BinaryEncoder::mapStart()
-{
+void BinaryEncoder::mapStart() {
 }
 
-void BinaryEncoder::mapEnd()
-{
+void BinaryEncoder::mapEnd() {
     doEncodeLong(0);
 }
 
-void BinaryEncoder::setItemCount(size_t count)
-{
+void BinaryEncoder::setItemCount(size_t count) {
     if (count == 0) {
         throw Exception("Count cannot be zero");
     }
     doEncodeLong(count);
 }
 
-void BinaryEncoder::startItem()
-{
+void BinaryEncoder::startItem() {
 }
 
-void BinaryEncoder::encodeUnionIndex(size_t e)
-{
+void BinaryEncoder::encodeUnionIndex(size_t e) {
     doEncodeLong(e);
 }
 
@@ -158,11 +138,9 @@ int64_t BinaryEncoder::byteCount() const {
     return out_.byteCount();
 }
 
-
-void BinaryEncoder::doEncodeLong(int64_t l)
-{
-    std::array<uint8_t, 10> bytes;
-    size_t size = encodeInt64(l, bytes);
+void BinaryEncoder::doEncodeLong(int64_t l) {
+    std::array<uint8_t, 10> bytes{};
+    auto size = encodeInt64(l, bytes);
     out_.writeBytes(bytes.data(), size);
 }
 }   // namespace avro
diff --git a/lang/c++/impl/Compiler.cc b/lang/c++/impl/Compiler.cc
index 6453db8..f7ab8ff 100644
--- a/lang/c++/impl/Compiler.cc
+++ b/lang/c++/impl/Compiler.cc
@@ -17,6 +17,7 @@
  */
 #include <boost/algorithm/string/replace.hpp>
 #include <sstream>
+#include <utility>
 
 #include "Compiler.hh"
 #include "Types.hh"
@@ -38,13 +39,12 @@ using json::Object;
 using json::Array;
 using json::EntityType;
 
-typedef map<Name, NodePtr> SymbolTable;
+using SymbolTable = map<Name, NodePtr>;
 
 
 // #define DEBUG_VERBOSE
 
-static NodePtr makePrimitive(const string& t)
-{
+static NodePtr makePrimitive(const string &t) {
     if (t == "null") {
         return NodePtr(new NodePrimitive(AVRO_NULL));
     } else if (t == "boolean") {
@@ -66,35 +66,31 @@ static NodePtr makePrimitive(const string& t)
     }
 }
 
-static NodePtr makeNode(const json::Entity& e, SymbolTable& st, const string &ns);
+static NodePtr makeNode(const json::Entity &e, SymbolTable &st, const string &ns);
 
-template <typename T>
-concepts::SingleAttribute<T> asSingleAttribute(const T& t)
-{
+template<typename T>
+concepts::SingleAttribute<T> asSingleAttribute(const T &t) {
     concepts::SingleAttribute<T> n;
     n.add(t);
     return n;
 }
 
-static bool isFullName(const string &s)
-{
+static bool isFullName(const string &s) {
     return s.find('.') != string::npos;
 }
 
-static Name getName(const string &name, const string &ns)
-{
+static Name getName(const string &name, const string &ns) {
     return (isFullName(name)) ? Name(name) : Name(name, ns);
 }
 
-static NodePtr makeNode(const string &t, SymbolTable &st, const string &ns)
-{
+static NodePtr makeNode(const string &t, SymbolTable &st, const string &ns) {
     NodePtr result = makePrimitive(t);
     if (result) {
         return result;
     }
     Name n = getName(t, ns);
 
-    SymbolTable::const_iterator it = st.find(n);
+    auto it = st.find(n);
     if (it != st.end()) {
         return NodePtr(new NodeSymbolic(asSingleAttribute(n), it->second));
     }
@@ -103,25 +99,16 @@ static NodePtr makeNode(const string &t, SymbolTable &st, const string &ns)
 
 /** Returns "true" if the field is in the container */
 // e.g.: can be false for non-mandatory fields
-bool containsField(const Object& m, const string& fieldName) {
-    Object::const_iterator it = m.find(fieldName);
+bool containsField(const Object &m, const string &fieldName) {
+    auto it = m.find(fieldName);
     return (it != m.end());
 }
 
-const json::Object::const_iterator findField(const Entity& e,
-    const Object& m, const string& fieldName)
-{
-    Object::const_iterator it = m.find(fieldName);
-    if (it == m.end()) {
-        throw Exception(boost::format("Missing Json field \"%1%\": %2%") %
-            fieldName % e.toString());
-    } else {
-        return it;
-    }
-}
+json::Object::const_iterator findField(const Entity &e,
+                                       const Object &m, const string &fieldName);
 
-template <typename T> void ensureType(const Entity &e, const string &name)
-{
+template<typename T>
+void ensureType(const Entity &e, const string &name) {
     if (e.type() != json::type_traits<T>::type()) {
         throw Exception(boost::format("Json field \"%1%\" is not a %2%: %3%") %
             name % json::type_traits<T>::name() % e.toString());
@@ -129,37 +116,29 @@ template <typename T> void ensureType(const Entity &e, const string &name)
 }
 
 string getStringField(const Entity &e, const Object &m,
-                             const string &fieldName)
-{
-    Object::const_iterator it = findField(e, m, fieldName);
+                      const string &fieldName) {
+    auto it = findField(e, m, fieldName);
     ensureType<string>(it->second, fieldName);
     return it->second.stringValue();
 }
 
-const Array& getArrayField(const Entity& e, const Object& m,
-                           const string& fieldName)
-{
-    Object::const_iterator it = findField(e, m, fieldName);
-    ensureType<Array >(it->second, fieldName);
-    return it->second.arrayValue();
-}
+const Array &getArrayField(const Entity &e, const Object &m,
+                           const string &fieldName);
 
-const int64_t getLongField(const Entity& e, const Object& m,
-                           const string& fieldName)
-{
-    Object::const_iterator it = findField(e, m, fieldName);
+int64_t getLongField(const Entity &e, const Object &m,
+                     const string &fieldName) {
+    auto it = findField(e, m, fieldName);
     ensureType<int64_t>(it->second, fieldName);
     return it->second.longValue();
 }
 
 // Unescape double quotes (") for de-serialization.  This method complements the
 // method NodeImpl::escape() which is used for serialization.
-static void unescape(string& s) {
+static void unescape(string &s) {
     boost::replace_all(s, "\\\"", "\"");
 }
 
-const string getDocField(const Entity& e, const Object& m)
-{
+string getDocField(const Entity &e, const Object &m) {
     string doc = getStringField(e, m, "doc");
     unescape(doc);
     return doc;
@@ -169,32 +148,29 @@ struct Field {
     const string name;
     const NodePtr schema;
     const GenericDatum defaultValue;
-    Field(const string& n, const NodePtr& v, GenericDatum dv) :
-        name(n), schema(v), defaultValue(dv) { }
+    Field(string n, NodePtr v, GenericDatum dv) :
+        name(std::move(n)), schema(std::move(v)), defaultValue(std::move(dv)) {}
 };
 
-static void assertType(const Entity& e, EntityType et)
-{
+static void assertType(const Entity &e, EntityType et) {
     if (e.type() != et) {
         throw Exception(boost::format("Unexpected type for default value: "
-            "Expected %1%, but found %2% in line %3%") %
-                json::typeToString(et) % json::typeToString(e.type()) %
-                e.line());
+                                      "Expected %1%, but found %2% in line %3%") %
+            json::typeToString(et) % json::typeToString(e.type()) %
+            e.line());
     }
 }
 
-static vector<uint8_t> toBin(const string& s)
-{
+static vector<uint8_t> toBin(const string &s) {
     vector<uint8_t> result(s.size());
-    if (s.size() > 0) {
+    if (!s.empty()) {
         std::copy(s.c_str(), s.c_str() + s.size(), result.data());
     }
     return result;
 }
 
 static GenericDatum makeGenericDatum(NodePtr n,
-        const Entity& e, const SymbolTable& st)
-{
+                                     const Entity &e, const SymbolTable &st) {
     Type t = n->type();
     EntityType dt = e.type();
 
@@ -203,127 +179,109 @@ static GenericDatum makeGenericDatum(NodePtr n,
         t = n->type();
     }
     switch (t) {
-    case AVRO_STRING:
-        assertType(e, json::etString);
-        return GenericDatum(e.stringValue());
-    case AVRO_BYTES:
-        assertType(e, json::etString);
-        return GenericDatum(toBin(e.bytesValue()));
-    case AVRO_INT:
-        assertType(e, json::etLong);
-        return GenericDatum(static_cast<int32_t>(e.longValue()));
-    case AVRO_LONG:
-        assertType(e, json::etLong);
-        return GenericDatum(e.longValue());
-    case AVRO_FLOAT:
-        if (dt == json::etLong) {
-            return GenericDatum(static_cast<float>(e.longValue()));
-        }
-        assertType(e, json::etDouble);
-        return GenericDatum(static_cast<float>(e.doubleValue()));
-    case AVRO_DOUBLE:
-        if (dt == json::etLong) {
-            return GenericDatum(static_cast<double>(e.longValue()));
+        case AVRO_STRING:assertType(e, json::etString);
+            return GenericDatum(e.stringValue());
+        case AVRO_BYTES:assertType(e, json::etString);
+            return GenericDatum(toBin(e.bytesValue()));
+        case AVRO_INT:assertType(e, json::etLong);
+            return GenericDatum(static_cast<int32_t>(e.longValue()));
+        case AVRO_LONG:assertType(e, json::etLong);
+            return GenericDatum(e.longValue());
+        case AVRO_FLOAT:
+            if (dt == json::etLong) {
+                return GenericDatum(static_cast<float>(e.longValue()));
+            }
+            assertType(e, json::etDouble);
+            return GenericDatum(static_cast<float>(e.doubleValue()));
+        case AVRO_DOUBLE:
+            if (dt == json::etLong) {
+                return GenericDatum(static_cast<double>(e.longValue()));
+            }
+            assertType(e, json::etDouble);
+            return GenericDatum(e.doubleValue());
+        case AVRO_BOOL:assertType(e, json::etBool);
+            return GenericDatum(e.boolValue());
+        case AVRO_NULL:assertType(e, json::etNull);
+            return GenericDatum();
+        case AVRO_RECORD: {
+            assertType(e, json::etObject);
+            GenericRecord result(n);
+            const map<string, Entity> &v = e.objectValue();
+            for (size_t i = 0; i < n->leaves(); ++i) {
+                auto it = v.find(n->nameAt(i));
+                if (it == v.end()) {
+                    throw Exception(boost::format(
+                        "No value found in default for %1%") % n->nameAt(i));
+                }
+                result.setFieldAt(i,
+                                  makeGenericDatum(n->leafAt(i), it->second, st));
+            }
+            return GenericDatum(n, result);
         }
-        assertType(e, json::etDouble);
-        return GenericDatum(e.doubleValue());
-    case AVRO_BOOL:
-        assertType(e, json::etBool);
-        return GenericDatum(e.boolValue());
-    case AVRO_NULL:
-        assertType(e, json::etNull);
-        return GenericDatum();
-    case AVRO_RECORD:
-    {
-        assertType(e, json::etObject);
-        GenericRecord result(n);
-        const map<string, Entity>& v = e.objectValue();
-        for (size_t i = 0; i < n->leaves(); ++i) {
-            map<string, Entity>::const_iterator it = v.find(n->nameAt(i));
-            if (it == v.end()) {
-                throw Exception(boost::format(
-                    "No value found in default for %1%") % n->nameAt(i));
+        case AVRO_ENUM:assertType(e, json::etString);
+            return GenericDatum(n, GenericEnum(n, e.stringValue()));
+        case AVRO_ARRAY: {
+            assertType(e, json::etArray);
+            GenericArray result(n);
+            const vector<Entity> &elements = e.arrayValue();
+            for (const auto &element : elements) {
+                result.value().push_back(makeGenericDatum(n->leafAt(0), element, st));
             }
-            result.setFieldAt(i,
-                makeGenericDatum(n->leafAt(i), it->second, st));
+            return GenericDatum(n, result);
         }
-        return GenericDatum(n, result);
-    }
-    case AVRO_ENUM:
-        assertType(e, json::etString);
-        return GenericDatum(n, GenericEnum(n, e.stringValue()));
-    case AVRO_ARRAY:
-    {
-        assertType(e, json::etArray);
-        GenericArray result(n);
-        const vector<Entity>& elements = e.arrayValue();
-        for (vector<Entity>::const_iterator it = elements.begin();
-            it != elements.end(); ++it) {
-            result.value().push_back(makeGenericDatum(n->leafAt(0), *it, st));
+        case AVRO_MAP: {
+            assertType(e, json::etObject);
+            GenericMap result(n);
+            const map<string, Entity> &v = e.objectValue();
+            for (const auto &it : v) {
+                result.value().push_back(make_pair(it.first,
+                                                   makeGenericDatum(n->leafAt(1), it.second, st)));
+            }
+            return GenericDatum(n, result);
         }
-        return GenericDatum(n, result);
-    }
-    case AVRO_MAP:
-    {
-        assertType(e, json::etObject);
-        GenericMap result(n);
-        const map<string, Entity>& v = e.objectValue();
-        for (map<string, Entity>::const_iterator it = v.begin();
-            it != v.end(); ++it) {
-            result.value().push_back(make_pair(it->first,
-                makeGenericDatum(n->leafAt(1), it->second, st)));
+        case AVRO_UNION: {
+            GenericUnion result(n);
+            result.selectBranch(0);
+            result.datum() = makeGenericDatum(n->leafAt(0), e, st);
+            return GenericDatum(n, result);
         }
-        return GenericDatum(n, result);
-    }
-    case AVRO_UNION:
-    {
-        GenericUnion result(n);
-        result.selectBranch(0);
-        result.datum() = makeGenericDatum(n->leafAt(0), e, st);
-        return GenericDatum(n, result);
-    }
-    case AVRO_FIXED:
-        assertType(e, json::etString);
-        return GenericDatum(n, GenericFixed(n, toBin(e.bytesValue())));
-    default:
-        throw Exception(boost::format("Unknown type: %1%") % t);
+        case AVRO_FIXED:assertType(e, json::etString);
+            return GenericDatum(n, GenericFixed(n, toBin(e.bytesValue())));
+        default:throw Exception(boost::format("Unknown type: %1%") % t);
     }
-    return GenericDatum();
 }
 
-
-static Field makeField(const Entity& e, SymbolTable& st, const string& ns)
-{
-    const Object& m = e.objectValue();
-    const string& n = getStringField(e, m, "name");
-    Object::const_iterator it = findField(e, m, "type");
-    map<string, Entity>::const_iterator it2 = m.find("default");
+static Field makeField(const Entity &e, SymbolTable &st, const string &ns) {
+    const Object &m = e.objectValue();
+    const string &n = getStringField(e, m, "name");
+    auto it = findField(e, m, "type");
+    auto it2 = m.find("default");
     NodePtr node = makeNode(it->second, st, ns);
     if (containsField(m, "doc")) {
         node->setDoc(getDocField(e, m));
     }
     GenericDatum d = (it2 == m.end()) ? GenericDatum() :
-        makeGenericDatum(node, it2->second, st);
+                     makeGenericDatum(node, it2->second, st);
     return Field(n, node, d);
 }
 
 // Extended makeRecordNode (with doc).
-static NodePtr makeRecordNode(const Entity& e, const Name& name,
-                              const string* doc, const Object& m,
-                              SymbolTable& st, const string& ns) {
-    const Array& v = getArrayField(e, m, "fields");
+static NodePtr makeRecordNode(const Entity &e, const Name &name,
+                              const string *doc, const Object &m,
+                              SymbolTable &st, const string &ns) {
+    const Array &v = getArrayField(e, m, "fields");
     concepts::MultiAttribute<string> fieldNames;
     concepts::MultiAttribute<NodePtr> fieldValues;
     vector<GenericDatum> defaultValues;
 
-    for (Array::const_iterator it = v.begin(); it != v.end(); ++it) {
-        Field f = makeField(*it, st, ns);
+    for (const auto &it : v) {
+        Field f = makeField(it, st, ns);
         fieldNames.add(f.name);
         fieldValues.add(f.schema);
         defaultValues.push_back(f.defaultValue);
     }
-    NodeRecord* node;
-    if (doc == NULL) {
+    NodeRecord *node;
+    if (doc == nullptr) {
         node = new NodeRecord(asSingleAttribute(name), fieldValues, fieldNames,
                               defaultValues);
     } else {
@@ -333,12 +291,12 @@ static NodePtr makeRecordNode(const Entity& e, const Name& name,
     return NodePtr(node);
 }
 
-static LogicalType makeLogicalType(const Entity& e, const Object& m) {
+static LogicalType makeLogicalType(const Entity &e, const Object &m) {
     if (!containsField(m, "logicalType")) {
         return LogicalType(LogicalType::NONE);
     }
 
-    const std::string& typeField = getStringField(e, m, "logicalType");
+    const std::string &typeField = getStringField(e, m, "logicalType");
 
     if (typeField == "decimal") {
         LogicalType decimalType(LogicalType::DECIMAL);
@@ -347,7 +305,7 @@ static LogicalType makeLogicalType(const Entity& e, const Object& m) {
             if (containsField(m, "scale")) {
                 decimalType.setScale(getLongField(e, m, "scale"));
             }
-        } catch (Exception& ex) {
+        } catch (Exception &ex) {
             // If any part of the logical type is malformed, per the standard we
             // must ignore the whole attribute.
             return LogicalType(LogicalType::NONE);
@@ -373,17 +331,16 @@ static LogicalType makeLogicalType(const Entity& e, const Object& m) {
     return LogicalType(t);
 }
 
-static NodePtr makeEnumNode(const Entity& e,
-    const Name& name, const Object& m)
-{
-    const Array& v = getArrayField(e, m, "symbols");
+static NodePtr makeEnumNode(const Entity &e,
+                            const Name &name, const Object &m) {
+    const Array &v = getArrayField(e, m, "symbols");
     concepts::MultiAttribute<string> symbols;
-    for (Array::const_iterator it = v.begin(); it != v.end(); ++it) {
-        if (it->type() != json::etString) {
+    for (const auto &it : v) {
+        if (it.type() != json::etString) {
             throw Exception(boost::format("Enum symbol not a string: %1%") %
-                it->toString());
+                it.toString());
         }
-        symbols.add(it->stringValue());
+        symbols.add(it.stringValue());
     }
     NodePtr node = NodePtr(new NodeEnum(asSingleAttribute(name), symbols));
     if (containsField(m, "doc")) {
@@ -392,9 +349,8 @@ static NodePtr makeEnumNode(const Entity& e,
     return node;
 }
 
-static NodePtr makeFixedNode(const Entity& e,
-    const Name& name, const Object& m)
-{
+static NodePtr makeFixedNode(const Entity &e,
+                             const Name &name, const Object &m) {
     int v = static_cast<int>(getLongField(e, m, "size"));
     if (v <= 0) {
         throw Exception(boost::format("Size for fixed is not positive: %1%") %
@@ -408,10 +364,9 @@ static NodePtr makeFixedNode(const Entity& e,
     return node;
 }
 
-static NodePtr makeArrayNode(const Entity& e, const Object& m,
-    SymbolTable& st, const string& ns)
-{
-    Object::const_iterator it = findField(e, m, "items");
+static NodePtr makeArrayNode(const Entity &e, const Object &m,
+                             SymbolTable &st, const string &ns) {
+    auto it = findField(e, m, "items");
     NodePtr node = NodePtr(new NodeArray(
         asSingleAttribute(makeNode(it->second, st, ns))));
     if (containsField(m, "doc")) {
@@ -420,10 +375,9 @@ static NodePtr makeArrayNode(const Entity& e, const Object& m,
     return node;
 }
 
-static NodePtr makeMapNode(const Entity& e, const Object& m,
-    SymbolTable& st, const string& ns)
-{
-    Object::const_iterator it = findField(e, m, "values");
+static NodePtr makeMapNode(const Entity &e, const Object &m,
+                           SymbolTable &st, const string &ns) {
+    auto it = findField(e, m, "values");
 
     NodePtr node = NodePtr(new NodeMap(
         asSingleAttribute(makeNode(it->second, st, ns))));
@@ -433,20 +387,19 @@ static NodePtr makeMapNode(const Entity& e, const Object& m,
     return node;
 }
 
-static Name getName(const Entity& e, const Object& m, const string& ns)
-{
-    const string& name = getStringField(e, m, "name");
+static Name getName(const Entity &e, const Object &m, const string &ns) {
+    const string &name = getStringField(e, m, "name");
 
     if (isFullName(name)) {
         return Name(name);
     } else {
-        Object::const_iterator it = m.find("namespace");
+        auto it = m.find("namespace");
         if (it != m.end()) {
             if (it->second.type() != json::type_traits<string>::type()) {
                 throw Exception(boost::format(
                     "Json field \"%1%\" is not a %2%: %3%") %
-                        "namespace" % json::type_traits<string>::name() %
-                        it->second.toString());
+                    "namespace" % json::type_traits<string>::name() %
+                    it->second.toString());
             }
             Name result = Name(name, it->second.stringValue());
             return result;
@@ -455,10 +408,9 @@ static Name getName(const Entity& e, const Object& m, const string& ns)
     }
 }
 
-static NodePtr makeNode(const Entity& e, const Object& m,
-    SymbolTable& st, const string& ns)
-{
-    const string& type = getStringField(e, m, "type");
+static NodePtr makeNode(const Entity &e, const Object &m,
+                        SymbolTable &st, const string &ns) {
+    const string &type = getStringField(e, m, "type");
     NodePtr result;
     if (type == "record" || type == "error" ||
         type == "enum" || type == "fixed") {
@@ -475,13 +427,13 @@ static NodePtr makeNode(const Entity& e, const Object& m,
                     *std::dynamic_pointer_cast<NodeRecord>(result));
             } else {  // No doc
                 NodePtr r =
-                    makeRecordNode(e, nm, NULL, m, st, nm.ns());
+                    makeRecordNode(e, nm, nullptr, m, st, nm.ns());
                 (std::dynamic_pointer_cast<NodeRecord>(r))
                     ->swap(*std::dynamic_pointer_cast<NodeRecord>(result));
             }
         } else {
             result = (type == "enum") ? makeEnumNode(e, nm, m) :
-                makeFixedNode(e, nm, m);
+                     makeFixedNode(e, nm, m);
             st[nm] = result;
         }
     } else if (type == "array") {
@@ -495,7 +447,7 @@ static NodePtr makeNode(const Entity& e, const Object& m,
     if (result) {
         try {
             result->setLogicalType(makeLogicalType(e, m));
-        } catch (Exception& ex) {
+        } catch (Exception &ex) {
             // Per the standard we must ignore the logical type attribute if it
             // is malformed.
         }
@@ -503,72 +455,73 @@ static NodePtr makeNode(const Entity& e, const Object& m,
     }
 
     throw Exception(boost::format("Unknown type definition: %1%")
-        % e.toString());
+                        % e.toString());
 }
 
-static NodePtr makeNode(const Entity& e, const Array& m,
-    SymbolTable& st, const string& ns)
-{
+static NodePtr makeNode(const Entity &e, const Array &m,
+                        SymbolTable &st, const string &ns) {
     concepts::MultiAttribute<NodePtr> mm;
-    for (Array::const_iterator it = m.begin(); it != m.end(); ++it) {
-        mm.add(makeNode(*it, st, ns));
+    for (const auto &it : m) {
+        mm.add(makeNode(it, st, ns));
     }
     return NodePtr(new NodeUnion(mm));
 }
 
-static NodePtr makeNode(const json::Entity& e, SymbolTable& st, const string& ns)
-{
+static NodePtr makeNode(const json::Entity &e, SymbolTable &st, const string &ns) {
     switch (e.type()) {
-    case json::etString:
-        return makeNode(e.stringValue(), st, ns);
-    case json::etObject:
-        return makeNode(e, e.objectValue(), st, ns);
-    case json::etArray:
-        return makeNode(e, e.arrayValue(), st, ns);
-    default:
-        throw Exception(boost::format("Invalid Avro type: %1%") % e.toString());
+        case json::etString:return makeNode(e.stringValue(), st, ns);
+        case json::etObject:return makeNode(e, e.objectValue(), st, ns);
+        case json::etArray:return makeNode(e, e.arrayValue(), st, ns);
+        default:throw Exception(boost::format("Invalid Avro type: %1%") % e.toString());
+    }
+}
+json::Object::const_iterator findField(const Entity &e, const Object &m, const string &fieldName) {
+    auto it = m.find(fieldName);
+    if (it == m.end()) {
+        throw Exception(boost::format("Missing Json field \"%1%\": %2%") %
+            fieldName % e.toString());
+    } else {
+        return it;
     }
 }
+const Array &getArrayField(const Entity &e, const Object &m, const string &fieldName) {
+    auto it = findField(e, m, fieldName);
+    ensureType<Array>(it->second, fieldName);
+    return it->second.arrayValue();
+}
 
-ValidSchema compileJsonSchemaFromStream(InputStream& is)
-{
+ValidSchema compileJsonSchemaFromStream(InputStream &is) {
     json::Entity e = json::loadEntity(is);
     SymbolTable st;
     NodePtr n = makeNode(e, st, "");
     return ValidSchema(n);
 }
 
-AVRO_DECL ValidSchema compileJsonSchemaFromFile(const char* filename)
-{
+AVRO_DECL ValidSchema compileJsonSchemaFromFile(const char *filename) {
     std::unique_ptr<InputStream> s = fileInputStream(filename);
     return compileJsonSchemaFromStream(*s);
 }
 
-AVRO_DECL ValidSchema compileJsonSchemaFromMemory(const uint8_t* input, size_t len)
-{
+AVRO_DECL ValidSchema compileJsonSchemaFromMemory(const uint8_t *input, size_t len) {
     return compileJsonSchemaFromStream(*memoryInputStream(input, len));
 }
 
-AVRO_DECL ValidSchema compileJsonSchemaFromString(const char* input)
-{
-    return compileJsonSchemaFromMemory(reinterpret_cast<const uint8_t*>(input),
-        ::strlen(input));
+AVRO_DECL ValidSchema compileJsonSchemaFromString(const char *input) {
+    return compileJsonSchemaFromMemory(reinterpret_cast<const uint8_t *>(input),
+                                       ::strlen(input));
 }
 
-AVRO_DECL ValidSchema compileJsonSchemaFromString(const string& input)
-{
+AVRO_DECL ValidSchema compileJsonSchemaFromString(const string &input) {
     return compileJsonSchemaFromMemory(
-        reinterpret_cast<const uint8_t*>(input.data()), input.size());
+        reinterpret_cast<const uint8_t *>(input.data()), input.size());
 }
 
-static ValidSchema compile(std::istream& is)
-{
+static ValidSchema compile(std::istream &is) {
     std::unique_ptr<InputStream> in = istreamInputStream(is);
     return compileJsonSchemaFromStream(*in);
 }
 
-void compileJsonSchema(std::istream &is, ValidSchema &schema)
-{
+void compileJsonSchema(std::istream &is, ValidSchema &schema) {
     if (!is.good()) {
         throw Exception("Input stream is not good");
     }
@@ -576,8 +529,7 @@ void compileJsonSchema(std::istream &is, ValidSchema &schema)
     schema = compile(is);
 }
 
-AVRO_DECL bool compileJsonSchema(std::istream &is, ValidSchema &schema, string &error)
-{
+AVRO_DECL bool compileJsonSchema(std::istream &is, ValidSchema &schema, string &error) {
     try {
         compileJsonSchema(is, schema);
         return true;
diff --git a/lang/c++/impl/LogicalType.cc b/lang/c++/impl/LogicalType.cc
index a0d9cc3..b583f44 100644
--- a/lang/c++/impl/LogicalType.cc
+++ b/lang/c++/impl/LogicalType.cc
@@ -53,30 +53,30 @@ void LogicalType::printJson(std::ostream& os) const {
     case LogicalType::NONE:
         break;
     case LogicalType::DECIMAL:
-        os << "\"logicalType\": \"decimal\"";
+        os << R"("logicalType": "decimal")";
         os << ", \"precision\": " << precision_;
         os << ", \"scale\": " << scale_;
         break;
     case DATE:
-        os << "\"logicalType\": \"date\"";
+        os << R"("logicalType": "date")";
         break;
     case TIME_MILLIS:
-        os << "\"logicalType\": \"time-millis\"";
+        os << R"("logicalType": "time-millis")";
         break;
     case TIME_MICROS:
-        os << "\"logicalType\": \"time-micros\"";
+        os << R"("logicalType": "time-micros")";
         break;
     case TIMESTAMP_MILLIS:
-        os << "\"logicalType\": \"timestamp-millis\"";
+        os << R"("logicalType": "timestamp-millis")";
         break;
     case TIMESTAMP_MICROS:
-        os << "\"logicalType\": \"timestamp-micros\"";
+        os << R"("logicalType": "timestamp-micros")";
         break;
     case DURATION:
-        os << "\"logicalType\": \"duration\"";
+        os << R"("logicalType": "duration")";
         break;
     case UUID:
-        os << "\"logicalType\": \"uuid\"";
+        os << R"("logicalType": "uuid")";
         break;
     }
 }
diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc
index bb510cc..f9c8506 100644
--- a/lang/c++/impl/Node.cc
+++ b/lang/c++/impl/Node.cc
@@ -24,21 +24,17 @@ namespace avro {
 
 using std::string;
 
-Node::~Node()
-{ }
+Node::~Node() = default;
 
-Name::Name(const std::string& name)
-{
+Name::Name(const std::string &name) {
     fullname(name);
 }
 
-const string Name::fullname() const
-{
+string Name::fullname() const {
     return (ns_.empty()) ? simpleName_ : ns_ + "." + simpleName_;
 }
 
-void Name::fullname(const string& name)
-{
+void Name::fullname(const string &name) {
     string::size_type n = name.find_last_of('.');
     if (n == string::npos) {
         simpleName_ = name;
@@ -50,35 +46,30 @@ void Name::fullname(const string& name)
     check();
 }
 
-bool Name::operator < (const Name& n) const
-{
-    return (ns_ < n.ns_) ? true :
-        (n.ns_ < ns_) ? false :
-        (simpleName_ < n.simpleName_);
+bool Name::operator<(const Name &n) const {
+    return (ns_ < n.ns_) || (!(n.ns_ < ns_) && (simpleName_ < n.simpleName_));
 }
 
-static bool invalidChar1(char c)
-{
+static bool invalidChar1(char c) {
     return !isalnum(c) && c != '_' && c != '.' && c != '$';
 }
 
-static bool invalidChar2(char c)
-{
+static bool invalidChar2(char c) {
     return !isalnum(c) && c != '_';
 }
 
-void Name::check() const
-{
-    if (! ns_.empty() && (ns_[0] == '.' || ns_[ns_.size() - 1] == '.' || std::find_if(ns_.begin(), ns_.end(), invalidChar1) != ns_.end())) {
+void Name::check() const {
+    if (!ns_.empty() && (ns_[0] == '.' || ns_[ns_.size() - 1] == '.'
+        || std::find_if(ns_.begin(), ns_.end(), invalidChar1) != ns_.end())) {
         throw Exception("Invalid namespace: " + ns_);
     }
-    if (simpleName_.empty() || std::find_if(simpleName_.begin(), simpleName_.end(), invalidChar2) != simpleName_.end()) {
+    if (simpleName_.empty()
+        || std::find_if(simpleName_.begin(), simpleName_.end(), invalidChar2) != simpleName_.end()) {
         throw Exception("Invalid name: " + simpleName_);
     }
 }
 
-bool Name::operator == (const Name& n) const
-{
+bool Name::operator==(const Name &n) const {
     return ns_ == n.ns_ && simpleName_ == n.simpleName_;
 }
 
@@ -87,72 +78,71 @@ void Node::setLogicalType(LogicalType logicalType) {
 
     // Check that the logical type is applicable to the node type.
     switch (logicalType.type()) {
-    case LogicalType::NONE:
-        break;
-    case LogicalType::DECIMAL: {
-        if (type_ != AVRO_BYTES && type_ != AVRO_FIXED) {
-            throw Exception("DECIMAL logical type can annotate "
-                            "only BYTES or FIXED type");
-        }
-        if (type_ == AVRO_FIXED) {
-            // Max precision that can be supported by the current size of
-            // the FIXED type.
-            long maxPrecision = floor(log10(2.0) * (8.0 * fixedSize() - 1));
-            if (logicalType.precision() > maxPrecision) {
-                throw Exception(
-                    boost::format(
-                        "DECIMAL precision %1% is too large for the "
-                        "FIXED type of size %2%, precision cannot be "
-                        "larget than %3%") % logicalType.precision() %
-                        fixedSize() % maxPrecision);
+        case LogicalType::NONE:break;
+        case LogicalType::DECIMAL: {
+            if (type_ != AVRO_BYTES && type_ != AVRO_FIXED) {
+                throw Exception("DECIMAL logical type can annotate "
+                                "only BYTES or FIXED type");
             }
+            if (type_ == AVRO_FIXED) {
+                // Max precision that can be supported by the current size of
+                // the FIXED type.
+                long maxPrecision = floor(log10(2.0) * (8.0 * fixedSize() - 1));
+                if (logicalType.precision() > maxPrecision) {
+                    throw Exception(
+                        boost::format(
+                            "DECIMAL precision %1% is too large for the "
+                            "FIXED type of size %2%, precision cannot be "
+                            "larget than %3%") % logicalType.precision() %
+                            fixedSize() % maxPrecision);
+                }
+            }
+            if (logicalType.scale() > logicalType.precision()) {
+                throw Exception("DECIMAL scale cannot exceed precision");
+            }
+            break;
         }
-        if (logicalType.scale() > logicalType.precision()) {
-            throw Exception("DECIMAL scale cannot exceed precision");
-        }
-        break;
-    }
-    case LogicalType::DATE:
-        if (type_ != AVRO_INT) {
-            throw Exception("DATE logical type can only annotate INT type");
-        }
-        break;
-    case LogicalType::TIME_MILLIS:
-        if (type_ != AVRO_INT) {
-            throw Exception("TIME-MILLIS logical type can only annotate "
-                            "INT type");
-        }
-        break;
-    case LogicalType::TIME_MICROS:
-        if (type_ != AVRO_LONG) {
-            throw Exception("TIME-MICROS logical type can only annotate "
-                            "LONG type");
-        }
-        break;
-    case LogicalType::TIMESTAMP_MILLIS:
-        if (type_ != AVRO_LONG) {
-            throw Exception("TIMESTAMP-MILLIS logical type can only annotate "
-                            "LONG type");
-        }
-        break;
-    case LogicalType::TIMESTAMP_MICROS:
-        if (type_ != AVRO_LONG) {
-            throw Exception("TIMESTAMP-MICROS logical type can only annotate "
-                            "LONG type");
-        }
-        break;
-    case LogicalType::DURATION:
-        if (type_ != AVRO_FIXED || fixedSize() != 12) {
-            throw Exception("DURATION logical type can only annotate "
-                            "FIXED type of size 12");
-        }
-        break;
-    case LogicalType::UUID:
-        if (type_ != AVRO_STRING) {
-            throw Exception("UUID logical type can only annotate "
-                            "STRING type");
-        }
-        break;
+        case LogicalType::DATE:
+            if (type_ != AVRO_INT) {
+                throw Exception("DATE logical type can only annotate INT type");
+            }
+            break;
+        case LogicalType::TIME_MILLIS:
+            if (type_ != AVRO_INT) {
+                throw Exception("TIME-MILLIS logical type can only annotate "
+                                "INT type");
+            }
+            break;
+        case LogicalType::TIME_MICROS:
+            if (type_ != AVRO_LONG) {
+                throw Exception("TIME-MICROS logical type can only annotate "
+                                "LONG type");
+            }
+            break;
+        case LogicalType::TIMESTAMP_MILLIS:
+            if (type_ != AVRO_LONG) {
+                throw Exception("TIMESTAMP-MILLIS logical type can only annotate "
+                                "LONG type");
+            }
+            break;
+        case LogicalType::TIMESTAMP_MICROS:
+            if (type_ != AVRO_LONG) {
+                throw Exception("TIMESTAMP-MICROS logical type can only annotate "
+                                "LONG type");
+            }
+            break;
+        case LogicalType::DURATION:
+            if (type_ != AVRO_FIXED || fixedSize() != 12) {
+                throw Exception("DURATION logical type can only annotate "
+                                "FIXED type of size 12");
+            }
+            break;
+        case LogicalType::UUID:
+            if (type_ != AVRO_STRING) {
+                throw Exception("UUID logical type can only annotate "
+                                "STRING type");
+            }
+            break;
     }
 
     logicalType_ = logicalType;
diff --git a/lang/c++/impl/NodeImpl.cc b/lang/c++/impl/NodeImpl.cc
index 4a0acb9..3e32062 100644
--- a/lang/c++/impl/NodeImpl.cc
+++ b/lang/c++/impl/NodeImpl.cc
@@ -18,11 +18,9 @@
 
 
 #include <sstream>
-#include <iomanip>
-#include <boost/algorithm/string/replace.hpp>
+#include <utility>
 #include "NodeImpl.hh"
 
-
 using std::string;
 namespace avro {
 
@@ -30,59 +28,50 @@ namespace {
 
 // Escape string for serialization.
 string escape(const string &unescaped) {
-  string s;
-  s.reserve(unescaped.length());
-  for (std::string::const_iterator it = unescaped.begin(); it != unescaped.end(); ++it) {
-    char c = *it;
-    switch (c) {
-      case '\\':
-      case '"':
-      case '/':
-        s += '\\';
-        s += c;
-        break;
-      case '\b':
-        s += '\\';
-        s += 'b';
-        break;
-      case '\f':
-        s += '\f';
-        break;
-      case '\n':
-        s += '\\';
-        s += 'n';
-        break;
-      case '\r':
-        s += '\\';
-        s += 'r';
-        break;
-      case '\t':
-        s += '\\';
-        s += 't';
-        break;
-      default:
-        if (!std::iscntrl(c, std::locale::classic())) {
-          s += c;
-          continue;
+    string s;
+    s.reserve(unescaped.length());
+    for (char c : unescaped) {
+        switch (c) {
+            case '\\':
+            case '"':
+            case '/':s += '\\';
+                s += c;
+                break;
+            case '\b':s += '\\';
+                s += 'b';
+                break;
+            case '\f':s += '\f';
+                break;
+            case '\n':s += '\\';
+                s += 'n';
+                break;
+            case '\r':s += '\\';
+                s += 'r';
+                break;
+            case '\t':s += '\\';
+                s += 't';
+                break;
+            default:
+                if (!std::iscntrl(c, std::locale::classic())) {
+                    s += c;
+                    continue;
+                }
+                s += intToHex(static_cast<unsigned int>(c));
+                break;
         }
-        s += intToHex(static_cast<unsigned int>(c));
-        break;
     }
-  }
-  return s;
+    return s;
 }
 
 // Wrap an indentation in a struct for ostream operator<<
 struct indent {
-    indent(int depth) :
-        d(depth)
-    { }
+    explicit indent(int depth) :
+        d(depth) {}
     int d;
 };
 
 /// ostream operator for indent
-std::ostream& operator <<(std::ostream &os, indent x)
-{
+std::ostream &operator<<(std::ostream &os, indent x) {
     static const string spaces("    ");
     while (x.d--) {
         os << spaces;
@@ -95,46 +84,43 @@ std::ostream& operator <<(std::ostream &os, indent x)
 const int kByteStringSize = 6;
 
 SchemaResolution
-NodePrimitive::resolve(const Node &reader) const
-{
+NodePrimitive::resolve(const Node &reader) const {
     if (type() == reader.type()) {
         return RESOLVE_MATCH;
     }
 
-    switch ( type() ) {
+    switch (type()) {
 
-      case AVRO_INT:
+        case AVRO_INT:
 
-        if ( reader.type() == AVRO_LONG ) {
-            return RESOLVE_PROMOTABLE_TO_LONG;
-        }
+            if (reader.type() == AVRO_LONG) {
+                return RESOLVE_PROMOTABLE_TO_LONG;
+            }
 
-        // fall-through intentional
+            // fall-through intentional
 
-      case AVRO_LONG:
+        case AVRO_LONG:
 
-        if (reader.type() == AVRO_FLOAT) {
-            return RESOLVE_PROMOTABLE_TO_FLOAT;
-        }
+            if (reader.type() == AVRO_FLOAT) {
+                return RESOLVE_PROMOTABLE_TO_FLOAT;
+            }
 
-        // fall-through intentional
+            // fall-through intentional
 
-      case AVRO_FLOAT:
+        case AVRO_FLOAT:
 
-        if (reader.type() == AVRO_DOUBLE) {
-            return RESOLVE_PROMOTABLE_TO_DOUBLE;
-        }
+            if (reader.type() == AVRO_DOUBLE) {
+                return RESOLVE_PROMOTABLE_TO_DOUBLE;
+            }
 
-      default:
-        break;
+        default:break;
     }
 
     return furtherResolution(reader);
 }
 
 SchemaResolution
-NodeRecord::resolve(const Node &reader) const
-{
+NodeRecord::resolve(const Node &reader) const {
     if (reader.type() == AVRO_RECORD) {
         if (name() == reader.name()) {
             return RESOLVE_MATCH;
@@ -144,8 +130,7 @@ NodeRecord::resolve(const Node &reader) const
 }
 
 SchemaResolution
-NodeEnum::resolve(const Node &reader) const
-{
+NodeEnum::resolve(const Node &reader) const {
     if (reader.type() == AVRO_ENUM) {
         return (name() == reader.name()) ? RESOLVE_MATCH : RESOLVE_NO_MATCH;
     }
@@ -153,8 +138,7 @@ NodeEnum::resolve(const Node &reader) const
 }
 
 SchemaResolution
-NodeArray::resolve(const Node &reader) const
-{
+NodeArray::resolve(const Node &reader) const {
     if (reader.type() == AVRO_ARRAY) {
         const NodePtr &arrayType = leafAt(0);
         return arrayType->resolve(*reader.leafAt(0));
@@ -163,8 +147,7 @@ NodeArray::resolve(const Node &reader) const
 }
 
 SchemaResolution
-NodeMap::resolve(const Node &reader) const
-{
+NodeMap::resolve(const Node &reader) const {
     if (reader.type() == AVRO_MAP) {
         const NodePtr &mapType = leafAt(1);
         return mapType->resolve(*reader.leafAt(1));
@@ -173,8 +156,7 @@ NodeMap::resolve(const Node &reader) const
 }
 
 SchemaResolution
-NodeUnion::resolve(const Node &reader) const
-{
+NodeUnion::resolve(const Node &reader) const {
 
     // If the writer is union, resolution only needs to occur when the selected
     // type of the writer is known, so this function is not very helpful.
@@ -184,7 +166,7 @@ NodeUnion::resolve(const Node &reader) const
     // found.
 
     SchemaResolution match = RESOLVE_NO_MATCH;
-    for (size_t i=0; i < leaves(); ++i) {
+    for (size_t i = 0; i < leaves(); ++i) {
         const NodePtr &node = leafAt(i);
         SchemaResolution thisMatch = node->resolve(reader);
         if (thisMatch == RESOLVE_MATCH) {
@@ -199,28 +181,25 @@ NodeUnion::resolve(const Node &reader) const
 }
 
 SchemaResolution
-NodeFixed::resolve(const Node &reader) const
-{
+NodeFixed::resolve(const Node &reader) const {
     if (reader.type() == AVRO_FIXED) {
         return (
-                (reader.fixedSize() == fixedSize()) &&
-                (reader.name() == name())
-            ) ?
-            RESOLVE_MATCH : RESOLVE_NO_MATCH;
+                   (reader.fixedSize() == fixedSize()) &&
+                       (reader.name() == name())
+               ) ?
+               RESOLVE_MATCH : RESOLVE_NO_MATCH;
     }
     return furtherResolution(reader);
 }
 
 SchemaResolution
-NodeSymbolic::resolve(const Node &reader) const
-{
+NodeSymbolic::resolve(const Node &reader) const {
     const NodePtr &node = leafAt(0);
     return node->resolve(reader);
 }
 
 void
-NodePrimitive::printJson(std::ostream &os, int depth) const
-{
+NodePrimitive::printJson(std::ostream &os, int depth) const {
     bool hasLogicalType = logicalType().type() != LogicalType::NONE;
 
     if (hasLogicalType) {
@@ -234,38 +213,35 @@ NodePrimitive::printJson(std::ostream &os, int depth) const
         logicalType().printJson(os);
         os << "\n}";
     }
-    if (getDoc().size()) {
-        os << ",\n" << indent(depth) << "\"doc\": \""
+    if (!getDoc().empty()) {
+        os << ",\n" << indent(depth) << R"("doc": ")"
            << escape(getDoc()) << "\"";
     }
 }
 
 void
-NodeSymbolic::printJson(std::ostream &os, int depth) const
-{
+NodeSymbolic::printJson(std::ostream &os, int depth) const {
     os << '\"' << nameAttribute_.get() << '\"';
-    if (getDoc().size()) {
-        os << ",\n" << indent(depth) << "\"doc\": \""
+    if (!getDoc().empty()) {
+        os << ",\n" << indent(depth) << R"("doc": ")"
            << escape(getDoc()) << "\"";
     }
 }
 
-static void printName(std::ostream& os, const Name& n, int depth)
-{
+static void printName(std::ostream &os, const Name &n, int depth) {
     if (!n.ns().empty()) {
-        os << indent(depth) << "\"namespace\": \"" << n.ns() << "\",\n";
+        os << indent(depth) << R"("namespace": ")" << n.ns() << "\",\n";
     }
-    os << indent(depth) << "\"name\": \"" << n.simpleName() << "\",\n";
+    os << indent(depth) << R"("name": ")" << n.simpleName() << "\",\n";
 }
 
 void
-NodeRecord::printJson(std::ostream &os, int depth) const
-{
+NodeRecord::printJson(std::ostream &os, int depth) const {
     os << "{\n";
     os << indent(++depth) << "\"type\": \"record\",\n";
     printName(os, nameAttribute_.get(), depth);
-    if (getDoc().size()) {
-        os << indent(depth) << "\"doc\": \""
+    if (!getDoc().empty()) {
+        os << indent(depth) << R"("doc": ")"
            << escape(getDoc()) << "\",\n";
     }
     os << indent(depth) << "\"fields\": [";
@@ -279,19 +255,19 @@ NodeRecord::printJson(std::ostream &os, int depth) const
             os << ',';
         }
         os << '\n' << indent(depth) << "{\n";
-        os << indent(++depth) << "\"name\": \"" << leafNameAttributes_.get(i) << "\",\n";
+        os << indent(++depth) << R"("name": ")" << leafNameAttributes_.get(i) << "\",\n";
         os << indent(depth) << "\"type\": ";
         leafAttributes_.get(i)->printJson(os, depth);
 
         if (!defaultValues.empty()) {
-          if (!defaultValues[i].isUnion() &&
-              defaultValues[i].type() == AVRO_NULL) {
-            // No "default" field.
-          } else {
-            os << ",\n" << indent(depth) << "\"default\": ";
-            leafAttributes_.get(i)->printDefaultToJson(defaultValues[i], os,
-                                                       depth);
-          }
+            if (!defaultValues[i].isUnion() &&
+                defaultValues[i].type() == AVRO_NULL) {
+                // No "default" field.
+            } else {
+                os << ",\n" << indent(depth) << "\"default\": ";
+                leafAttributes_.get(i)->printDefaultToJson(defaultValues[i], os,
+                                                           depth);
+            }
         }
         os << '\n';
         os << indent(--depth) << '}';
@@ -302,163 +278,168 @@ NodeRecord::printJson(std::ostream &os, int depth) const
 
 void NodePrimitive::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                        int depth) const {
-  assert(isPrimitive(g.type()));
-
-  switch (g.type()) {
-    case AVRO_NULL:
-      os << "null";
-      break;
-    case AVRO_BOOL:
-      os << (g.value<bool>() ? "true" : "false");
-      break;
-    case AVRO_INT:
-      os << g.value<int32_t>();
-      break;
-    case AVRO_LONG:
-      os << g.value<int64_t>();
-      break;
-    case AVRO_FLOAT:
-      os << g.value<float>();
-      break;
-    case AVRO_DOUBLE:
-      os << g.value<double>();
-      break;
-    case AVRO_STRING:
-      os << "\"" << escape(g.value<string>()) << "\"";
-      break;
-    case AVRO_BYTES: {
-      // Convert to a string:
-      const std::vector<uint8_t> &vg = g.value<std::vector<uint8_t> >();
-      string s;
-      s.resize(vg.size() * kByteStringSize);
-      for (unsigned int i = 0; i < vg.size(); i++) {
-        string hex_string = intToHex(static_cast<int>(vg[i]));
-        s.replace(i*kByteStringSize, kByteStringSize, hex_string);
-      }
-      os << "\"" << s << "\"";
-    } break;
-    default:
-      break;
-  }
+    assert(isPrimitive(g.type()));
+
+    switch (g.type()) {
+        case AVRO_NULL:os << "null";
+            break;
+        case AVRO_BOOL:os << (g.value<bool>() ? "true" : "false");
+            break;
+        case AVRO_INT:os << g.value<int32_t>();
+            break;
+        case AVRO_LONG:os << g.value<int64_t>();
+            break;
+        case AVRO_FLOAT:os << g.value<float>();
+            break;
+        case AVRO_DOUBLE:os << g.value<double>();
+            break;
+        case AVRO_STRING:os << "\"" << escape(g.value<string>()) << "\"";
+            break;
+        case AVRO_BYTES: {
+            // Convert to a string:
+            const auto &vg = g.value<std::vector<uint8_t> >();
+            string s;
+            s.resize(vg.size() * kByteStringSize);
+            for (unsigned int i = 0; i < vg.size(); i++) {
+                string hex_string = intToHex(static_cast<int>(vg[i]));
+                s.replace(i * kByteStringSize, kByteStringSize, hex_string);
+            }
+            os << "\"" << s << "\"";
+        }
+            break;
+        default:break;
+    }
 }
 
 void NodeEnum::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                   int depth) const {
-  assert(g.type() == AVRO_ENUM);
-  os << "\"" << g.value<GenericEnum>().symbol() << "\"";
+    assert(g.type() == AVRO_ENUM);
+    os << "\"" << g.value<GenericEnum>().symbol() << "\"";
 }
 
 void NodeFixed::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                    int depth) const {
-  assert(g.type() == AVRO_FIXED);
-  // ex: "\uOOff"
-  // Convert to a string
-  const std::vector<uint8_t> &vg = g.value<GenericFixed>().value();
-  string s;
-  s.resize(vg.size() * kByteStringSize);
-  for (unsigned int i = 0; i < vg.size(); i++) {
-    string hex_string = intToHex(static_cast<int>(vg[i]));
-    s.replace(i*kByteStringSize, kByteStringSize, hex_string);
-  }
-  os << "\"" << s << "\"";
+    assert(g.type() == AVRO_FIXED);
+    // ex: "\uOOff"
+    // Convert to a string
+    const std::vector<uint8_t> &vg = g.value<GenericFixed>().value();
+    string s;
+    s.resize(vg.size() * kByteStringSize);
+    for (unsigned int i = 0; i < vg.size(); i++) {
+        string hex_string = intToHex(static_cast<int>(vg[i]));
+        s.replace(i * kByteStringSize, kByteStringSize, hex_string);
+    }
+    os << "\"" << s << "\"";
 }
 
 void NodeUnion::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                    int depth) const {
-  leafAt(0)->printDefaultToJson(g, os, depth);
+    leafAt(0)->printDefaultToJson(g, os, depth);
 }
 
 void NodeArray::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                    int depth) const {
-  assert(g.type() == AVRO_ARRAY);
-  // ex: "default": [1]
-  if (g.value<GenericArray>().value().empty()) {
-    os << "[]";
-  } else {
-    os << "[\n";
-    depth++;
-
-    // Serialize all values of the array with recursive calls:
-    for (unsigned int i = 0; i < g.value<GenericArray>().value().size(); i++) {
-      if (i > 0) {
-        os << ",\n";
-      }
-      os << indent(depth);
-      leafAt(0)->printDefaultToJson(g.value<GenericArray>().value()[i], os,
-                                    depth);
+    assert(g.type() == AVRO_ARRAY);
+    // ex: "default": [1]
+    if (g.value<GenericArray>().value().empty()) {
+        os << "[]";
+    } else {
+        os << "[\n";
+        depth++;
+
+        // Serialize all values of the array with recursive calls:
+        for (unsigned int i = 0; i < g.value<GenericArray>().value().size(); i++) {
+            if (i > 0) {
+                os << ",\n";
+            }
+            os << indent(depth);
+            leafAt(0)->printDefaultToJson(g.value<GenericArray>().value()[i], os,
+                                          depth);
+        }
+        os << "\n" << indent(--depth) << "]";
     }
-    os << "\n" << indent(--depth) << "]";
-  }
 }
 
 void NodeSymbolic::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                       int depth) const {
-  getNode()->printDefaultToJson(g, os, depth);
+    getNode()->printDefaultToJson(g, os, depth);
 }
 
 void NodeRecord::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                     int depth) const {
-  assert(g.type() == AVRO_RECORD);
-  if (g.value<GenericRecord>().fieldCount() == 0) {
-    os << "{}";
-  } else {
-    os << "{\n";
-
-    // Serialize all fields of the record with recursive calls:
-    for (unsigned int i = 0; i < g.value<GenericRecord>().fieldCount(); i++) {
-      if (i == 0) {
-        ++depth;
-      } else {  // i > 0
-        os << ",\n";
-      }
-
-      os << indent(depth) << "\"";
-      assert(i < leaves());
-      os << leafNameAttributes_.get(i);
-      os << "\": ";
-
-      // Recursive call on child node to be able to get the name attribute
-      // (In case of a record we need the name of the leaves (contained in
-      // 'this'))
-      leafAt(i)->printDefaultToJson(g.value<GenericRecord>().fieldAt(i), os,
-                                    depth);
+    assert(g.type() == AVRO_RECORD);
+    if (g.value<GenericRecord>().fieldCount() == 0) {
+        os << "{}";
+    } else {
+        os << "{\n";
+
+        // Serialize all fields of the record with recursive calls:
+        for (auto i = 0; i < g.value<GenericRecord>().fieldCount(); i++) {
+            if (i == 0) {
+                ++depth;
+            } else {  // i > 0
+                os << ",\n";
+            }
+
+            os << indent(depth) << "\"";
+            assert(i < leaves());
+            os << leafNameAttributes_.get(i);
+            os << "\": ";
+
+            // Recursive call on child node to be able to get the name attribute
+            // (In case of a record we need the name of the leaves (contained in
+            // 'this'))
+            leafAt(i)->printDefaultToJson(g.value<GenericRecord>().fieldAt(i), os,
+                                          depth);
+        }
+        os << "\n" << indent(--depth) << "}";
+    }
+}
+NodeRecord::NodeRecord(const HasName &name,
+                       const MultiLeaves &fields,
+                       const LeafNames &fieldsNames,
+                       std::vector<GenericDatum> dv) :
+    NodeImplRecord(AVRO_RECORD, name, fields, fieldsNames, NoSize()),
+    defaultValues(std::move(dv)) {
+    for (size_t i = 0; i < leafNameAttributes_.size(); ++i) {
+        if (!nameIndex_.add(leafNameAttributes_.get(i), i)) {
+            throw Exception(boost::format(
+                "Cannot add duplicate field: %1%") %
+                leafNameAttributes_.get(i));
+        }
     }
-    os << "\n" << indent(--depth) << "}";
-  }
 }
 
 void NodeMap::printDefaultToJson(const GenericDatum &g, std::ostream &os,
                                  int depth) const {
-  assert(g.type() == AVRO_MAP);
-  //{"a": 1}
-  if (g.value<GenericMap>().value().empty()) {
-    os << "{}";
-  } else {
-    os << "{\n";
-
-    for (unsigned int i = 0; i < g.value<GenericMap>().value().size(); i++) {
-      if (i == 0) {
-        ++depth;
-      } else {
-        os << ",\n";
-      }
-      os << indent(depth) << "\"" << g.value<GenericMap>().value()[i].first
-         << "\": ";
-
-      leafAt(i)->printDefaultToJson(g.value<GenericMap>().value()[i].second, os,
-                                    depth);
+    assert(g.type() == AVRO_MAP);
+    if (g.value<GenericMap>().value().empty()) {
+        os << "{}";
+    } else {
+        os << "{\n";
+
+        for (auto i = 0; i < g.value<GenericMap>().value().size(); i++) {
+            if (i == 0) {
+                ++depth;
+            } else {
+                os << ",\n";
+            }
+            os << indent(depth) << "\"" << g.value<GenericMap>().value()[i].first
+               << "\": ";
+
+            leafAt(i)->printDefaultToJson(g.value<GenericMap>().value()[i].second, os,
+                                          depth);
+        }
+        os << "\n" << indent(--depth) << "}";
     }
-    os << "\n" << indent(--depth) << "}";
-  }
 }
 
 void
-NodeEnum::printJson(std::ostream &os, int depth) const
-{
+NodeEnum::printJson(std::ostream &os, int depth) const {
     os << "{\n";
     os << indent(++depth) << "\"type\": \"enum\",\n";
-    if (getDoc().size()) {
-        os << indent(depth) << "\"doc\": \""
+    if (!getDoc().empty()) {
+        os << indent(depth) << R"("doc": ")"
            << escape(getDoc()) << "\",\n";
     }
     printName(os, nameAttribute_.get(), depth);
@@ -478,38 +459,42 @@ NodeEnum::printJson(std::ostream &os, int depth) const
 }
 
 void
-NodeArray::printJson(std::ostream &os, int depth) const
-{
+NodeArray::printJson(std::ostream &os, int depth) const {
     os << "{\n";
-    os << indent(depth+1) << "\"type\": \"array\",\n";
-    if (getDoc().size()) {
-        os << indent(depth+1) << "\"doc\": \""
+    os << indent(depth + 1) << "\"type\": \"array\",\n";
+    if (!getDoc().empty()) {
+        os << indent(depth + 1) << R"("doc": ")"
            << escape(getDoc()) << "\",\n";
     }
-    os << indent(depth+1) <<  "\"items\": ";
-    leafAttributes_.get()->printJson(os, depth+1);
+    os << indent(depth + 1) << "\"items\": ";
+    leafAttributes_.get()->printJson(os, depth + 1);
     os << '\n';
     os << indent(depth) << '}';
 }
 
 void
-NodeMap::printJson(std::ostream &os, int depth) const
-{
+NodeMap::printJson(std::ostream &os, int depth) const {
     os << "{\n";
-    os << indent(depth+1) <<"\"type\": \"map\",\n";
-    if (getDoc().size()) {
-        os << indent(depth+1) << "\"doc\": \""
+    os << indent(depth + 1) << "\"type\": \"map\",\n";
+    if (!getDoc().empty()) {
+        os << indent(depth + 1) << R"("doc": ")"
            << escape(getDoc()) << "\",\n";
     }
-    os << indent(depth+1) << "\"values\": ";
-    leafAttributes_.get(1)->printJson(os, depth+1);
+    os << indent(depth + 1) << "\"values\": ";
+    leafAttributes_.get(1)->printJson(os, depth + 1);
     os << '\n';
     os << indent(depth) << '}';
 }
 
+NodeMap::NodeMap() :
+    NodeImplMap(AVRO_MAP) {
+    NodePtr key(new NodePrimitive(AVRO_STRING));
+    // FIXME: Calling virtual member function from constructor
+    doAddLeaf(key);
+}
+
 void
-NodeUnion::printJson(std::ostream &os, int depth) const
-{
+NodeUnion::printJson(std::ostream &os, int depth) const {
     os << "[\n";
     int fields = leafAttributes_.size();
     ++depth;
@@ -525,20 +510,19 @@ NodeUnion::printJson(std::ostream &os, int depth) const
 }
 
 void
-NodeFixed::printJson(std::ostream &os, int depth) const
-{
+NodeFixed::printJson(std::ostream &os, int depth) const {
     os << "{\n";
     os << indent(++depth) << "\"type\": \"fixed\",\n";
-    if (getDoc().size()) {
-        os << indent(depth) << "\"doc\": \""
+    if (!getDoc().empty()) {
+        os << indent(depth) << R"("doc": ")"
            << escape(getDoc()) << "\",\n";
     }
     printName(os, nameAttribute_.get(), depth);
     os << indent(depth) << "\"size\": " << sizeAttribute_.get();
 
     if (logicalType().type() != LogicalType::NONE) {
-      os << ",\n" << indent(depth);
-      logicalType().printJson(os);
+        os << ",\n" << indent(depth);
+        logicalType().printJson(os);
     }
 
     os << "\n" << indent(--depth) << '}';
diff --git a/lang/c++/impl/Schema.cc b/lang/c++/impl/Schema.cc
index e6cfa45..20f5f84 100644
--- a/lang/c++/impl/Schema.cc
+++ b/lang/c++/impl/Schema.cc
@@ -17,33 +17,19 @@
  */
 
 
+#include <utility>
+
 #include "Schema.hh"
 
 namespace avro {
 
-Schema::Schema()
-{ }
-
-Schema::~Schema()
-{ }
-
-Schema::Schema(const NodePtr &node) :
-    node_(node)
-{ }
-
-Schema::Schema(Node *node) :
-    node_(node)
-{ }
-
 RecordSchema::RecordSchema(const std::string &name) :
-    Schema(new NodeRecord)
-{
-    node_->setName(name);
+    Schema(new NodeRecord) {
+    node_->setName(Name(name));
 }
 
 void
-RecordSchema::addField(const std::string &name, const Schema &fieldSchema)
-{
+RecordSchema::addField(const std::string &name, const Schema &fieldSchema) {
     // add the name first. it will throw if the name is a duplicate, preventing
     // the leaf from being added
     node_->addName(name);
@@ -51,69 +37,59 @@ RecordSchema::addField(const std::string &name, const Schema &fieldSchema)
     node_->addLeaf(fieldSchema.root());
 }
 
-std::string RecordSchema::getDoc() const
-{
+std::string RecordSchema::getDoc() const {
     return node_->getDoc();
 }
-void RecordSchema::setDoc(const std::string& doc)
-{
+void RecordSchema::setDoc(const std::string &doc) {
     node_->setDoc(doc);
 }
 
 EnumSchema::EnumSchema(const std::string &name) :
-    Schema(new NodeEnum)
-{
-    node_->setName(name);
+    Schema(new NodeEnum) {
+    node_->setName(Name(name));
 }
 
 void
-EnumSchema::addSymbol(const std::string &symbol)
-{
+EnumSchema::addSymbol(const std::string &symbol) {
     node_->addName(symbol);
 }
 
 ArraySchema::ArraySchema(const Schema &itemsSchema) :
-    Schema(new NodeArray)
-{
+    Schema(new NodeArray) {
     node_->addLeaf(itemsSchema.root());
 }
 
 ArraySchema::ArraySchema(const ArraySchema &itemsSchema) :
-    Schema(new NodeArray)
-{
+    Schema(new NodeArray) {
     node_->addLeaf(itemsSchema.root());
 }
 
 MapSchema::MapSchema(const Schema &valuesSchema) :
-    Schema(new NodeMap)
-{
+    Schema(new NodeMap) {
     node_->addLeaf(valuesSchema.root());
 }
 
 MapSchema::MapSchema(const MapSchema &valuesSchema) :
-    Schema(new NodeMap)
-{
+    Schema(new NodeMap) {
     node_->addLeaf(valuesSchema.root());
 }
 
 UnionSchema::UnionSchema() :
-    Schema(new NodeUnion)
-{ }
+    Schema(new NodeUnion) {}
 
 void
-UnionSchema::addType(const Schema &typeSchema)
-{
-    if(typeSchema.type() == AVRO_UNION) {
+UnionSchema::addType(const Schema &typeSchema) {
+    if (typeSchema.type() == AVRO_UNION) {
         throw Exception("Cannot add unions to unions");
     }
 
-    if(typeSchema.type() == AVRO_RECORD) {
+    if (typeSchema.type() == AVRO_RECORD) {
         // check for duplicate records
         size_t types = node_->leaves();
-        for(size_t i = 0; i < types; ++i) {
+        for (size_t i = 0; i < types; ++i) {
             const NodePtr &leaf = node_->leafAt(i);
             // TODO, more checks?
-            if(leaf->type() == AVRO_RECORD && leaf->name() == typeSchema.root()->name()) {
+            if (leaf->type() == AVRO_RECORD && leaf->name() == typeSchema.root()->name()) {
                 throw Exception("Records in unions cannot have duplicate names");
             }
         }
@@ -123,17 +99,13 @@ UnionSchema::addType(const Schema &typeSchema)
 }
 
 FixedSchema::FixedSchema(int size, const std::string &name) :
-    Schema(new NodeFixed)
-{
+    Schema(new NodeFixed) {
     node_->setFixedSize(size);
-    node_->setName(name);
+    node_->setName(Name(name));
 }
 
-SymbolicSchema::SymbolicSchema(const Name &name, const NodePtr& link) :
-    Schema(new NodeSymbolic(HasName(name), link))
-{
+SymbolicSchema::SymbolicSchema(const Name &name, const NodePtr &link) :
+    Schema(new NodeSymbolic(HasName(name), link)) {
 }
 
-
-
 } // namespace avro
diff --git a/lang/c++/impl/Types.cc b/lang/c++/impl/Types.cc
index 6c9d702..977e3f0 100644
--- a/lang/c++/impl/Types.cc
+++ b/lang/c++/impl/Types.cc
@@ -21,7 +21,6 @@
 #include "Types.hh"
 
 namespace avro {
-
 namespace strings {
 const std::string typeToString[] = {
     "string",
@@ -41,8 +40,8 @@ const std::string typeToString[] = {
     "symbolic"
 };
 
-static_assert((sizeof(typeToString)/sizeof(std::string)) == (AVRO_NUM_TYPES+1),
-    "Incorrect Avro typeToString");
+static_assert((sizeof(typeToString) / sizeof(std::string)) == (AVRO_NUM_TYPES + 1),
+              "Incorrect Avro typeToString");
 
 } // namespace strings
 
@@ -51,31 +50,27 @@ static_assert((sizeof(typeToString)/sizeof(std::string)) == (AVRO_NUM_TYPES+1),
 // and it would be a problem for this flag if we ever supported more than 32 types
 static_assert(AVRO_NUM_TYPES < 32, "Too many Avro types");
 
-const std::string& toString(Type type)
-{
-    static std::string undefinedType = "Undefined type";
-    if (isAvroTypeOrPseudoType(type)) {
-        return strings::typeToString[type];
-    } else {
-        return undefinedType;
-    }
+const std::string &toString(Type type) noexcept {
+  static std::string undefinedType = "Undefined type";
+  if (isAvroTypeOrPseudoType(type)) {
+    return strings::typeToString[type];
+  } else {
+    return undefinedType;
+  }
 }
 
-std::ostream &operator<< (std::ostream &os, Type type)
-{
-    if(isAvroTypeOrPseudoType(type)) {
-        os << strings::typeToString[type];
-    }
-    else {
-        os << static_cast<int>(type);
-    }
-    return os;
+std::ostream &operator<<(std::ostream &os, Type type) {
+  if (isAvroTypeOrPseudoType(type)) {
+    os << strings::typeToString[type];
+  } else {
+    os << static_cast<int>(type);
+  }
+  return os;
 }
 
-std::ostream &operator<< (std::ostream &os, const Null &)
-{
-    os << "(null value)";
-    return os;
+std::ostream &operator<<(std::ostream &os, const Null &) {
+  os << "(null value)";
+  return os;
 }
 
 } // namespace avro
diff --git a/lang/c++/impl/ValidSchema.cc b/lang/c++/impl/ValidSchema.cc
index 74a3f84..d70f819 100644
--- a/lang/c++/impl/ValidSchema.cc
+++ b/lang/c++/impl/ValidSchema.cc
@@ -19,6 +19,7 @@
 #include <boost/format.hpp>
 #include <cctype>
 #include <sstream>
+#include <utility>
 
 #include "ValidSchema.hh"
 #include "Schema.hh"
@@ -32,111 +33,105 @@ using std::shared_ptr;
 using std::static_pointer_cast;
 
 namespace avro {
-typedef std::map<Name, NodePtr> SymbolMap;
+    using SymbolMap = std::map<Name, NodePtr>;
 
-static bool validate(const NodePtr &node, SymbolMap &symbolMap)
-{
-    if (! node->isValid()) {
-        throw Exception(format("Schema is invalid, due to bad node of type %1%")
-            % node->type());
-    }
+    static bool validate(const NodePtr &node, SymbolMap &symbolMap) {
+        if (!node->isValid()) {
+            throw Exception(format("Schema is invalid, due to bad node of type %1%")
+                            % node->type());
+        }
 
-    if (node->hasName()) {
-        const Name& nm = node->name();
-        SymbolMap::iterator it = symbolMap.find(nm);
-        bool found = it != symbolMap.end() && nm == it->first;
+        if (node->hasName()) {
+            const Name &nm = node->name();
+            // FIXME: replace "find" with "lower_bound". The author seems to have intended
+            // "lower_bound" here because of (1) the check for the contents of the iterator
+            // that follows and (2) use of the iterator in insert later in the code.
+            auto it = symbolMap.find(nm);
+            auto found = it != symbolMap.end() && nm == it->first;
+
+            if (node->type() == AVRO_SYMBOLIC) {
+                if (!found) {
+                    throw Exception(format("Symbolic name \"%1%\" is unknown") %
+                                    node->name());
+                }
 
-        if (node->type() == AVRO_SYMBOLIC) {
-            if (! found) {
-                throw Exception(format("Symbolic name \"%1%\" is unknown") %
-                    node->name());
-            }
+                shared_ptr<NodeSymbolic> symNode =
+                        static_pointer_cast<NodeSymbolic>(node);
 
-            shared_ptr<NodeSymbolic> symNode =
-                static_pointer_cast<NodeSymbolic>(node);
+                // if the symbolic link is already resolved, we return true,
+                // otherwise returning false will force it to be resolved
+                return symNode->isSet();
+            }
 
-            // if the symbolic link is already resolved, we return true,
-            // otherwise returning false will force it to be resolved
-            return symNode->isSet();
+            if (found) {
+                return false;
+            }
+            symbolMap.insert(it, make_pair(nm, node));
         }
 
-        if (found) {
-            return false;
+        node->lock();
+        auto leaves = node->leaves();
+        for (auto i = 0; i < leaves; ++i) {
+            const NodePtr &leaf(node->leafAt(i));
+
+            if (!validate(leaf, symbolMap)) {
+
+                // if validate returns false it means a node with this name already
+                // existed in the map, instead of keeping this node twice in the
+                // map (which could potentially create circular shared pointer
+                // links that would not be freed), replace this node with a
+                // symbolic link to the original one.
+
+                node->setLeafToSymbolic(i, symbolMap.find(leaf->name())->second);
+            }
         }
-        symbolMap.insert(it, make_pair(nm, node));
+
+        return true;
     }
 
-    node->lock();
-    size_t leaves = node->leaves();
-    for (size_t i = 0; i < leaves; ++i) {
-        const NodePtr &leaf(node->leafAt(i));
+    static void validate(const NodePtr &p) {
+        SymbolMap m;
+        validate(p, m);
+    }
 
-        if (! validate(leaf, symbolMap)) {
+    ValidSchema::ValidSchema(NodePtr root) : root_(std::move(root)) {
+        validate(root_);
+    }
 
-            // if validate returns false it means a node with this name already
-            // existed in the map, instead of keeping this node twice in the
-            // map (which could potentially create circular shared pointer
-            // links that could not be easily freed), replace this node with a
-            // symbolic link to the original one.
+    ValidSchema::ValidSchema(const Schema &schema) : root_(schema.root()) {
+        validate(root_);
+    }
 
-            node->setLeafToSymbolic(i, symbolMap.find(leaf->name())->second);
-        }
+    ValidSchema::ValidSchema() : root_(NullSchema().root()) {
+        validate(root_);
     }
 
-    return true;
-}
-
-static void validate(const NodePtr& p)
-{
-    SymbolMap m;
-    validate(p, m);
-}
-
-ValidSchema::ValidSchema(const NodePtr &root) : root_(root)
-{
-    validate(root_);
-}
-
-ValidSchema::ValidSchema(const Schema &schema) : root_(schema.root())
-{
-    validate(root_);
-}
-
-ValidSchema::ValidSchema() : root_(NullSchema().root())
-{
-    validate(root_);
-}
-
-void
-ValidSchema::setSchema(const Schema &schema)
-{
-    root_ = schema.root();
-    validate(root_);
-}
-
-void
-ValidSchema::toJson(std::ostream &os) const
-{
-    root_->printJson(os, 0);
-    os << '\n';
-}
-
-string
-ValidSchema::toJson(bool prettyPrint) const
-{
-    ostringstream oss;
-    toJson(oss);
-    if (!prettyPrint) {
-        return compactSchema(oss.str());
+    void
+    ValidSchema::setSchema(const Schema &schema) {
+        root_ = schema.root();
+        validate(root_);
     }
-    return oss.str();
-}
 
-void
-ValidSchema::toFlatList(std::ostream &os) const
-{
-    root_->printBasicInfo(os);
-}
+    void
+    ValidSchema::toJson(std::ostream &os) const {
+        root_->printJson(os, 0);
+        os << '\n';
+    }
+
+    string
+    ValidSchema::toJson(bool prettyPrint) const {
+        ostringstream oss;
+        toJson(oss);
+        if (!prettyPrint) {
+            return compactSchema(oss.str());
+        }
+        return oss.str();
+    }
+
+    void
+    ValidSchema::toFlatList(std::ostream &os) const {
+        root_->printBasicInfo(os);
+    }
 
 /*
  * compactSchema compacts and returns a formatted string representation
@@ -145,49 +140,49 @@ ValidSchema::toFlatList(std::ostream &os) const
  * in UTF-8 format. Note that this method is not responsible for validating
  * the schema.
  */
-string ValidSchema::compactSchema(const string& schema) {
-    bool insideQuote = false;
-    size_t newPos = 0;
-    string data(schema.data());
-
-    for (size_t currentPos = 0; currentPos < schema.size(); currentPos++) {
-        if (!insideQuote && std::isspace(data[currentPos])) {
-            // Skip the white spaces outside quotes.
-            continue;
-        }
+    string ValidSchema::compactSchema(const string &schema) {
+        auto insideQuote = false;
+        size_t newPos = 0;
+        string data = schema;
+
+        for (auto c : schema) {
+            if (!insideQuote && std::isspace(c)) {
+                // Skip the white spaces outside quotes.
+                continue;
+            }
 
-        if (data[currentPos] == '\"') {
-            // It is valid for a quote to be part of the value for some fields,
-            // e.g., the "doc" field.  In that case, the quote is expected to be
-            // escaped inside the schema.  Since the escape character '\\' could
-            // be escaped itself, we need to check whether there are an even
-            // number of consecutive slashes prior to the quote.
-            int leadingSlashes = 0;
-            for (int i = newPos - 1; i >= 0; i--) {
-                if (data[i] == '\\') {
-                    leadingSlashes++;
-                } else {
-                    break;
+            if (c == '\"') {
+                // It is valid for a quote to be part of the value for some fields,
+                // e.g., the "doc" field.  In that case, the quote is expected to be
+                // escaped inside the schema.  Since the escape character '\\' could
+                // be escaped itself, we need to check whether there are an even
+                // number of consecutive slashes prior to the quote.
+                auto leadingSlashes = 0;
+                for (int i = static_cast<int>(newPos) - 1; i >= 0; i--) {
+                    if (data[i] == '\\') {
+                        leadingSlashes++;
+                    } else {
+                        break;
+                    }
+                }
+                if (leadingSlashes % 2 == 0) {
+                    // Found a real quote which identifies either the start or the
+                    // end of a field name or value.
+                    insideQuote = !insideQuote;
                 }
             }
-            if (leadingSlashes % 2 == 0) {
-                // Found a real quote which identifies either the start or the
-                // end of a field name or value.
-                insideQuote = !insideQuote;
-            }
+            data[newPos++] = c;
         }
-        data[newPos++] = data[currentPos];
-    }
 
-    if (insideQuote) {
-        throw Exception("Schema is not well formed with mismatched quotes");
-    }
+        if (insideQuote) {
+            throw Exception("Schema is not well formed with mismatched quotes");
+        }
 
-    if (newPos < schema.size()) {
-        data.resize(newPos);
+        if (newPos < schema.size()) {
+            data.resize(newPos);
+        }
+        return data;
     }
-    return data;
-}
 
 } // namespace avro
 
diff --git a/lang/c++/impl/Validator.cc b/lang/c++/impl/Validator.cc
index 2e74b06..3901044 100644
--- a/lang/c++/impl/Validator.cc
+++ b/lang/c++/impl/Validator.cc
@@ -16,26 +16,26 @@
  * limitations under the License.
  */
 
+#include <utility>
+
 #include "Validator.hh"
 #include "ValidSchema.hh"
 #include "NodeImpl.hh"
 
 namespace avro {
 
-Validator::Validator(const ValidSchema &schema) :
-    schema_(schema),
+Validator::Validator(ValidSchema schema) :
+    schema_(std::move(schema)),
     nextType_(AVRO_NULL),
     expectedTypesFlag_(0),
     compoundStarted_(false),
     waitingForCount_(false),
-    count_(0)
-{
+    count_(0) {
     setupOperation(schema_.root());
 }
 
 void
-Validator::setWaitingForCount()
-{
+Validator::setWaitingForCount() {
     waitingForCount_ = true;
     count_ = 0;
     expectedTypesFlag_ = typeToFlag(AVRO_INT) | typeToFlag(AVRO_LONG);
@@ -43,34 +43,29 @@ Validator::setWaitingForCount()
 }
 
 void
-Validator::enumAdvance()
-{
-    if(compoundStarted_) {
+Validator::enumAdvance() {
+    if (compoundStarted_) {
         setWaitingForCount();
         compoundStarted_ = false;
-    }
-    else {
+    } else {
         waitingForCount_ = false;
         compoundStack_.pop_back();
     }
 }
 
 bool
-Validator::countingSetup()
-{
-    bool proceed = true;
-    if(compoundStarted_) {
+Validator::countingSetup() {
+    auto proceed = true;
+    if (compoundStarted_) {
         setWaitingForCount();
         compoundStarted_ = false;
         proceed = false;
-    }
-    else if(waitingForCount_) {
+    } else if (waitingForCount_) {
         waitingForCount_ = false;
-        if(count_ == 0) {
+        if (count_ == 0) {
             compoundStack_.pop_back();
             proceed = false;
-        }
-        else {
+        } else {
             counters_.push_back(static_cast<size_t>(count_));
         }
     }
@@ -79,27 +74,23 @@ Validator::countingSetup()
 }
 
 void
-Validator::countingAdvance()
-{
-    if(countingSetup()) {
-
-        size_t index = (compoundStack_.back().pos)++;
+Validator::countingAdvance() {
+    if (countingSetup()) {
+        auto index = (compoundStack_.back().pos)++;
         const NodePtr &node = compoundStack_.back().node;
 
-        if(index < node->leaves() ) {
+        if (index < node->leaves()) {
             setupOperation(node->leafAt(index));
-        }
-        else {
+        } else {
             compoundStack_.back().pos = 0;
             int count = --counters_.back();
-            if(count == 0) {
+            if (count == 0) {
                 counters_.pop_back();
                 compoundStarted_ = true;
                 nextType_ = node->type();
                 expectedTypesFlag_ = typeToFlag(nextType_);
-            }
-            else {
-                size_t index = (compoundStack_.back().pos)++;
+            } else {
+                index = (compoundStack_.back().pos)++;
                 setupOperation(node->leafAt(index));
             }
         }
@@ -107,58 +98,52 @@ Validator::countingAdvance()
 }
 
 void
-Validator::unionAdvance()
-{
-    if(compoundStarted_) {
+Validator::unionAdvance() {
+    if (compoundStarted_) {
         setWaitingForCount();
         compoundStarted_ = false;
-    }
-    else {
+    } else {
         waitingForCount_ = false;
         NodePtr node = compoundStack_.back().node;
 
-        if(count_ < static_cast<int64_t>(node->leaves())) {
+        if (count_ < static_cast<int64_t>(node->leaves())) {
             compoundStack_.pop_back();
             setupOperation(node->leafAt(static_cast<int>(count_)));
-        }
-        else {
+        } else {
             throw Exception(
                 boost::format("Union selection out of range, got %1%," \
                     " expecting 0-%2%")
-                    % count_ % (node->leaves() -1)
+                    % count_ % (node->leaves() - 1)
             );
         }
     }
 }
 
 void
-Validator::fixedAdvance()
-{
+Validator::fixedAdvance() {
     compoundStarted_ = false;
     compoundStack_.pop_back();
 }
 
 int
-Validator::nextSizeExpected() const
-{
+Validator::nextSizeExpected() const {
     return compoundStack_.back().node->fixedSize();
 }
 
 void
-Validator::doAdvance()
-{
-    typedef void (Validator::*AdvanceFunc)();
+Validator::doAdvance() {
+    using AdvanceFunc = void (Validator::*)();
 
     // only the compound types need advance functions here
     static const AdvanceFunc funcs[] = {
-        0, // string
-        0, // bytes
-        0, // int
-        0, // long
-        0, // float
-        0, // double
-        0, // bool
-        0, // null
+        nullptr, // string
+        nullptr, // bytes
+        nullptr, // int
+        nullptr, // long
+        nullptr, // float
+        nullptr, // double
+        nullptr, // bool
+        nullptr, // null
         &Validator::countingAdvance, // Record is treated like counting with count == 1
         &Validator::enumAdvance,
         &Validator::countingAdvance,
@@ -166,12 +151,12 @@ Validator::doAdvance()
         &Validator::unionAdvance,
         &Validator::fixedAdvance
     };
-    static_assert((sizeof(funcs)/sizeof(AdvanceFunc)) == (AVRO_NUM_TYPES),
-            "Invalid number of advance functions");
+    static_assert((sizeof(funcs) / sizeof(AdvanceFunc)) == (AVRO_NUM_TYPES),
+                  "Invalid number of advance functions");
 
     expectedTypesFlag_ = 0;
     // loop until we encounter a next expected type, or we've exited all compound types
-    while(!expectedTypesFlag_ && !compoundStack_.empty() ) {
+    while (!expectedTypesFlag_ && !compoundStack_.empty()) {
 
         Type type = compoundStack_.back().node->type();
 
@@ -184,25 +169,22 @@ Validator::doAdvance()
         ((this)->*(func))();
     }
 
-    if(compoundStack_.empty()) {
+    if (compoundStack_.empty()) {
         nextType_ = AVRO_NULL;
     }
 }
 
-void Validator::advance()
-{
-    if(!waitingForCount_) {
+void Validator::advance() {
+    if (!waitingForCount_) {
         doAdvance();
     }
 }
 
 void
-Validator::setCount(int64_t count)
-{
-    if(!waitingForCount_) {
+Validator::setCount(int64_t count) {
+    if (!waitingForCount_) {
         throw Exception("Not expecting count");
-    }
-    else if(count_ < 0) {
+    } else if (count_ < 0) {
         throw Exception("Count cannot be negative");
     }
     count_ = count;
@@ -211,8 +193,7 @@ Validator::setCount(int64_t count)
 }
 
 void
-Validator::setupFlag(Type type)
-{
+Validator::setupFlag(Type type) {
     // use flags instead of strictly types, so that we can be more lax about the type
     // (for example, a long should be able to accept an int type, but not vice versa)
     static const flag_t flags[] = {
@@ -231,18 +212,17 @@ Validator::setupFlag(Type type)
         typeToFlag(AVRO_UNION),
         typeToFlag(AVRO_FIXED)
     };
-    static_assert((sizeof(flags)/sizeof(flag_t)) == (AVRO_NUM_TYPES),
-            "Invalid number of avro type flags");
+    static_assert((sizeof(flags) / sizeof(flag_t)) == (AVRO_NUM_TYPES),
+                  "Invalid number of avro type flags");
 
     expectedTypesFlag_ = flags[type];
 }
 
 void
-Validator::setupOperation(const NodePtr &node)
-{
+Validator::setupOperation(const NodePtr &node) {
     nextType_ = node->type();
 
-    if(nextType_ == AVRO_SYMBOLIC) {
+    if (nextType_ == AVRO_SYMBOLIC) {
         NodePtr actualNode = resolveSymbol(node);
         assert(actualNode);
         setupOperation(actualNode);
@@ -253,28 +233,22 @@ Validator::setupOperation(const NodePtr &node)
 
     setupFlag(nextType_);
 
-    if(!isPrimitive(nextType_)) {
-        compoundStack_.push_back(CompoundType(node));
+    if (!isPrimitive(nextType_)) {
+        compoundStack_.emplace_back(node);
         compoundStarted_ = true;
     }
 }
 
 bool
-Validator::getCurrentRecordName(std::string &name) const
-{
-    bool found = false;
+Validator::getCurrentRecordName(std::string &name) const {
+    auto found = false;
     name.clear();
 
-    int idx = -1;
     // if the top of the stack is a record I want this record name
-    if(!compoundStack_.empty() && (isPrimitive(nextType_) || nextType_ == AVRO_RECORD)) {
-        idx = compoundStack_.size() -1;
-    }
-    else {
-        idx = compoundStack_.size() -2;
-    }
+    auto idx = static_cast<int>(compoundStack_.size() -
+        ((!compoundStack_.empty() && (isPrimitive(nextType_) || nextType_ == AVRO_RECORD)) ? 1 : 2));
 
-    if(idx >= 0 && compoundStack_[idx].node->type() == AVRO_RECORD) {
+    if (idx >= 0 && compoundStack_[idx].node->type() == AVRO_RECORD) {
         name = compoundStack_[idx].node->name().simpleName();
         found = true;
     }
@@ -282,15 +256,14 @@ Validator::getCurrentRecordName(std::string &name) const
 }
 
 bool
-Validator::getNextFieldName(std::string &name) const
-{
-    bool found = false;
+Validator::getNextFieldName(std::string &name) const {
+    auto found = false;
     name.clear();
-    int idx = isCompound(nextType_) ? compoundStack_.size()-2 : compoundStack_.size()-1;
-    if(idx >= 0 && compoundStack_[idx].node->type() == AVRO_RECORD) {
-        size_t pos = compoundStack_[idx].pos-1;
+    auto idx = static_cast<int>(compoundStack_.size() - (isCompound(nextType_) ? 2 : 1));
+    if (idx >= 0 && compoundStack_[idx].node->type() == AVRO_RECORD) {
+        size_t pos = compoundStack_[idx].pos - 1;
         const NodePtr &node = compoundStack_[idx].node;
-        if(pos < node->leaves()) {
+        if (pos < node->leaves()) {
             name = node->nameAt(pos);
             found = true;
         }
diff --git a/lang/c++/impl/Zigzag.cc b/lang/c++/impl/Zigzag.cc
index 0b38053..3638806 100644
--- a/lang/c++/impl/Zigzag.cc
+++ b/lang/c++/impl/Zigzag.cc
@@ -38,7 +38,6 @@ encodeInt64(int64_t input, std::array<uint8_t, 10> &output) noexcept {
     output[bytesOut++] = v;
     return bytesOut;
 }
-
 size_t
 encodeInt32(int32_t input, std::array<uint8_t, 5> &output) noexcept {
     auto val = encodeZigzag32(input);
diff --git a/lang/c++/impl/parsing/JsonCodec.cc b/lang/c++/impl/parsing/JsonCodec.cc
index 8bca298..c21b6ce 100644
--- a/lang/c++/impl/parsing/JsonCodec.cc
+++ b/lang/c++/impl/parsing/JsonCodec.cc
@@ -21,7 +21,7 @@
 #include <string>
 #include <map>
 #include <algorithm>
-#include <ctype.h>
+#include <cctype>
 #include <memory>
 #include <boost/math/special_functions/fpclassify.hpp>
 
@@ -59,7 +59,7 @@ class JsonGrammarGenerator : public ValidatingGrammarGenerator {
 static std::string nameOf(const NodePtr& n)
 {
     if (n->hasName()) {
-        return n->name();
+        return std::string(n->name());
     }
     std::ostringstream oss;
     oss << n->type();
diff --git a/lang/c++/test/DataFileTests.cc b/lang/c++/test/DataFileTests.cc
index 8c4605f..ca9cb9a 100644
--- a/lang/c++/test/DataFileTests.cc
+++ b/lang/c++/test/DataFileTests.cc
@@ -67,8 +67,8 @@ struct Integer {
     Integer(int64_t r) : re(r) { }
 };
 
-typedef Complex<int64_t> ComplexInteger;
-typedef Complex<double> ComplexDouble;
+using ComplexInteger = Complex<int64_t>;
+using ComplexDouble = Complex<double>;
 
 struct Double {
     double re;
@@ -196,7 +196,7 @@ public:
         filename(f), writerSchema(makeValidSchema(wsch)),
         readerSchema(makeValidSchema(rsch)), count(count) { }
 
-    typedef pair<ValidSchema, GenericDatum> Pair;
+    using Pair = pair<ValidSchema, GenericDatum>;
 
     void testCleanup() {
         BOOST_CHECK(boost::filesystem::remove(filename));
diff --git a/lang/c++/test/SchemaTests.cc b/lang/c++/test/SchemaTests.cc
index b7de980..cac8688 100644
--- a/lang/c++/test/SchemaTests.cc
+++ b/lang/c++/test/SchemaTests.cc
@@ -264,6 +264,10 @@ const char* compactSchemas[] = {
         "{\"name\":\"re2\",\"type\":\"long\",\"doc\":\"extra slashes\\\\\\\\\"}"
     "]}"};
 
+void testTypes() {
+    BOOST_CHECK_EQUAL(isAvroType(AVRO_BOOL), true);
+}
+
 static void testBasic(const char* schema)
 {
     BOOST_TEST_CHECKPOINT(schema);
@@ -469,6 +473,7 @@ init_unit_test_suite(int argc, char* argv[])
     using namespace boost::unit_test;
 
     test_suite* ts= BOOST_TEST_SUITE("Avro C++ unit tests for schemas");
+    ts->add(BOOST_TEST_CASE(&avro::schema::testTypes));
     ADD_PARAM_TEST(ts, avro::schema::testBasic, avro::schema::basicSchemas);
     ADD_PARAM_TEST(ts, avro::schema::testBasic_fail,
         avro::schema::basicSchemaErrors);
diff --git a/lang/c++/test/testgentest.cc b/lang/c++/test/testgentest.cc
index e456ed8..b56d4a4 100644
--- a/lang/c++/test/testgentest.cc
+++ b/lang/c++/test/testgentest.cc
@@ -286,7 +286,7 @@ struct TestCodeGenerator {
         // in this test I know choice was 0
         {
             BOOST_CHECK_EQUAL(rec1.anotherunion.choice, 0);
-            typedef std::vector<uint8_t> mytype;
+            using mytype = std::vector<uint8_t>;
             checkBytes(rec1.anotherunion.getValue<mytype>(), rec2.anotherunion.getValue<testgen::Union_of_bytes_null::T0>());
         }
 
@@ -452,7 +452,7 @@ struct TestSchemaResolving {
 
         {
             BOOST_CHECK_EQUAL(rec1.anotherunion.choice, 0);
-            typedef std::vector<uint8_t> mytype;
+            using mytype = std::vector<uint8_t>;
             checkBytes(rec1.anotherunion.getValue<mytype>(), rec2.anotherunion);
         }