Improve and simplify code with modern C++ features

Change-Id: I28d84df3087492ab2ecbeb91169a2cde12c9e31e
diff --git a/src/common.hpp b/src/common.hpp
index 6de1e07..d990d94 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -79,6 +79,8 @@
 using std::ref;
 using std::cref;
 
+using namespace std::string_literals;
+
 } // namespace ndn
 
 using namespace std::placeholders;
@@ -90,7 +92,7 @@
 namespace boost {
 #define NDN_CXX_SPECIALIZE_BOOST_IS_PLACEHOLDER_FOR_STD_PLACEHOLDER(N) \
   template<> \
-  struct is_placeholder<typename std::remove_const<decltype(_##N)>::type> \
+  struct is_placeholder<std::remove_const_t<decltype(_##N)>> \
   { \
     enum _vt { \
       value = N \
diff --git a/src/delegation-list.cpp b/src/delegation-list.cpp
index e21d100..91ea7af 100644
--- a/src/delegation-list.cpp
+++ b/src/delegation-list.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -33,7 +33,7 @@
 }
 
 DelegationList::Error::Error(const std::string& what, const std::exception& innerException)
-  : Error(what + std::string(": ") + innerException.what())
+  : Error(what + ": "s + innerException.what())
 {
 }
 
diff --git a/src/encoding/block-helpers.hpp b/src/encoding/block-helpers.hpp
index c66c0b9..acde49c 100644
--- a/src/encoding/block-helpers.hpp
+++ b/src/encoding/block-helpers.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -68,7 +68,7 @@
  *                    represented in R
  */
 template<typename R>
-typename std::enable_if<std::is_integral<R>::value, R>::type
+std::enable_if_t<std::is_integral<R>::value, R>
 readNonNegativeIntegerAs(const Block& block)
 {
   uint64_t value = readNonNegativeInteger(block);
@@ -88,10 +88,10 @@
  *           function may trigger unspecified behavior.
  */
 template<typename R>
-typename std::enable_if<std::is_enum<R>::value, R>::type
+std::enable_if_t<std::is_enum<R>::value, R>
 readNonNegativeIntegerAs(const Block& block)
 {
-  return static_cast<R>(readNonNegativeIntegerAs<typename std::underlying_type<R>::type>(block));
+  return static_cast<R>(readNonNegativeIntegerAs<std::underlying_type_t<R>>(block));
 }
 
 /** @brief Prepend an empty TLV element
@@ -231,11 +231,11 @@
 Block
 makeBinaryBlock(uint32_t type, Iterator first, Iterator last)
 {
-  using BinaryBlockHelper = typename std::conditional<
+  using BinaryBlockHelper = std::conditional_t<
     std::is_base_of<std::random_access_iterator_tag,
                     typename std::iterator_traits<Iterator>::iterator_category>::value,
     detail::BinaryBlockFast<Iterator>,
-    detail::BinaryBlockSlow<Iterator>>::type;
+    detail::BinaryBlockSlow<Iterator>>;
 
   return BinaryBlockHelper::makeBlock(type, first, last);
 }
diff --git a/src/encoding/nfd-constants.cpp b/src/encoding/nfd-constants.cpp
index 5c3189a..eebd4f3 100644
--- a/src/encoding/nfd-constants.cpp
+++ b/src/encoding/nfd-constants.cpp
@@ -121,7 +121,7 @@
     routeOrigin = ROUTE_ORIGIN_STATIC;
   else {
     // To reject negative numbers, we parse as a wider signed type, and compare with the range.
-    static_assert(std::numeric_limits<std::underlying_type<RouteOrigin>::type>::max() <=
+    static_assert(std::numeric_limits<std::underlying_type_t<RouteOrigin>>::max() <=
                   std::numeric_limits<int>::max(), "");
 
     int v = -1;
@@ -131,8 +131,8 @@
     catch (const boost::bad_lexical_cast&) {
     }
 
-    if (v >= std::numeric_limits<std::underlying_type<RouteOrigin>::type>::min() &&
-        v <= std::numeric_limits<std::underlying_type<RouteOrigin>::type>::max()) {
+    if (v >= std::numeric_limits<std::underlying_type_t<RouteOrigin>>::min() &&
+        v <= std::numeric_limits<std::underlying_type_t<RouteOrigin>>::max()) {
       routeOrigin = static_cast<RouteOrigin>(v);
     }
     else {
diff --git a/src/encoding/tlv.hpp b/src/encoding/tlv.hpp
index fc664c6..6a14a7c 100644
--- a/src/encoding/tlv.hpp
+++ b/src/encoding/tlv.hpp
@@ -354,7 +354,7 @@
  *  common ContiguousIterator types used with TLV decoding function templates.
  */
 template<typename Iterator,
-         typename DecayedIterator = typename std::decay<Iterator>::type,
+         typename DecayedIterator = std::decay_t<Iterator>,
          typename ValueType = typename std::iterator_traits<DecayedIterator>::value_type>
 constexpr bool
 shouldSelectContiguousReadNumber()
@@ -367,8 +367,8 @@
 }
 
 template<typename Iterator>
-class ReadNumber : public std::conditional<shouldSelectContiguousReadNumber<Iterator>(),
-                                           ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>::type
+class ReadNumber : public std::conditional_t<shouldSelectContiguousReadNumber<Iterator>(),
+                                             ReadNumberFast<Iterator>, ReadNumberSlow<Iterator>>
 {
 };
 
diff --git a/src/exclude.hpp b/src/exclude.hpp
index a5a2db6..77c9785 100644
--- a/src/exclude.hpp
+++ b/src/exclude.hpp
@@ -27,6 +27,7 @@
 #include "name-component.hpp"
 #include "encoding/encoding-buffer.hpp"
 
+#include <iterator>
 #include <map>
 
 namespace ndn {
@@ -222,17 +223,23 @@
     name::Component to;
   };
 
-  class const_iterator : public std::iterator<std::forward_iterator_tag, const Range>
+  class const_iterator
   {
   public:
+    using iterator_category = std::forward_iterator_tag;
+    using value_type        = const Range;
+    using difference_type   = std::ptrdiff_t;
+    using pointer           = value_type*;
+    using reference         = value_type&;
+
     const_iterator() = default;
 
     const_iterator(ExcludeMap::const_reverse_iterator it, ExcludeMap::const_reverse_iterator rend);
 
-    const Range&
+    reference
     operator*() const;
 
-    const Range*
+    pointer
     operator->() const;
 
     const_iterator&
@@ -347,14 +354,14 @@
   return !this->operator==(other);
 }
 
-inline const Exclude::Range&
+inline Exclude::const_iterator::reference
 Exclude::const_iterator::operator*() const
 {
   BOOST_ASSERT(m_it != m_rend);
   return m_range;
 }
 
-inline const Exclude::Range*
+inline Exclude::const_iterator::pointer
 Exclude::const_iterator::operator->() const
 {
   BOOST_ASSERT(m_it != m_rend);
diff --git a/src/ims/in-memory-storage.cpp b/src/ims/in-memory-storage.cpp
index 0dc7df7..3db250d 100644
--- a/src/ims/in-memory-storage.cpp
+++ b/src/ims/in-memory-storage.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -43,7 +43,7 @@
     m_ptr = &((*m_it)->getData());
   }
   else {
-    m_ptr = 0;
+    m_ptr = nullptr;
   }
 
   return *this;
@@ -57,13 +57,13 @@
   return i;
 }
 
-const Data&
+InMemoryStorage::const_iterator::reference
 InMemoryStorage::const_iterator::operator*()
 {
   return *m_ptr;
 }
 
-const Data*
+InMemoryStorage::const_iterator::pointer
 InMemoryStorage::const_iterator::operator->()
 {
   return m_ptr;
@@ -160,8 +160,8 @@
 void
 InMemoryStorage::insert(const Data& data, const time::milliseconds& mustBeFreshProcessingWindow)
 {
-  //check if identical Data/Name already exists
-  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().find(data.getFullName());
+  // check if identical Data/Name already exists
+  auto it = m_cache.get<byFullName>().find(data.getFullName());
   if (it != m_cache.get<byFullName>().end())
     return;
 
@@ -187,8 +187,7 @@
   entry->setData(data);
   if (m_scheduler != nullptr && mustBeFreshProcessingWindow > ZERO_WINDOW) {
     auto eventId = make_unique<util::scheduler::ScopedEventId>(*m_scheduler);
-    *eventId = m_scheduler->scheduleEvent(mustBeFreshProcessingWindow,
-                                          bind(&InMemoryStorageEntry::markStale, entry));
+    *eventId = m_scheduler->scheduleEvent(mustBeFreshProcessingWindow, [entry] { entry->markStale(); });
     entry->setMarkStaleEventId(std::move(eventId));
   }
   m_cache.insert(entry);
@@ -200,16 +199,16 @@
 shared_ptr<const Data>
 InMemoryStorage::find(const Name& name)
 {
-  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().lower_bound(name);
+  auto it = m_cache.get<byFullName>().lower_bound(name);
 
-  //if not found, return null
+  // if not found, return null
   if (it == m_cache.get<byFullName>().end()) {
-    return shared_ptr<const Data>();
+    return nullptr;
   }
 
-  //if the given name is not the prefix of the lower_bound, return null
+  // if the given name is not the prefix of the lower_bound, return null
   if (!name.isPrefixOf((*it)->getFullName())) {
-    return shared_ptr<const Data>();
+    return nullptr;
   }
 
   afterAccess(*it);
@@ -219,36 +218,35 @@
 shared_ptr<const Data>
 InMemoryStorage::find(const Interest& interest)
 {
-  //if the interest contains implicit digest, it is possible to directly locate a packet.
-  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>()
-                                                    .find(interest.getName());
+  // if the interest contains implicit digest, it is possible to directly locate a packet.
+  auto it = m_cache.get<byFullName>().find(interest.getName());
 
-  //if a packet is located by its full name, it must be the packet to return.
+  // if a packet is located by its full name, it must be the packet to return.
   if (it != m_cache.get<byFullName>().end()) {
     return ((*it)->getData()).shared_from_this();
   }
 
-  //if the packet is not discovered by last step, either the packet is not in the storage or
-  //the interest doesn't contains implicit digest.
+  // if the packet is not discovered by last step, either the packet is not in the storage or
+  // the interest doesn't contains implicit digest.
   it = m_cache.get<byFullName>().lower_bound(interest.getName());
 
   if (it == m_cache.get<byFullName>().end()) {
-    return shared_ptr<const Data>();
+    return nullptr;
   }
 
-  //to locate the element that has a just smaller name than the interest's
-  if (it != m_cache.get<byFullName>().begin())
+  // to locate the element that has a just smaller name than the interest's
+  if (it != m_cache.get<byFullName>().begin()) {
     it--;
+  }
 
   InMemoryStorageEntry* ret = selectChild(interest, it);
-  if (ret != 0) {
-    //let derived class do something with the entry
-    afterAccess(ret);
-    return ret->getData().shared_from_this();
+  if (ret == nullptr) {
+    return nullptr;
   }
-  else {
-    return shared_ptr<const Data>();
-  }
+
+  // let derived class do something with the entry
+  afterAccess(ret);
+  return ret->getData().shared_from_this();
 }
 
 InMemoryStorage::Cache::index<InMemoryStorage::byFullName>::type::iterator
@@ -268,99 +266,86 @@
 {
   BOOST_ASSERT(startingPoint != m_cache.get<byFullName>().end());
 
-  if (startingPoint != m_cache.get<byFullName>().begin())
-    {
-      BOOST_ASSERT((*startingPoint)->getFullName() < interest.getName());
-    }
+  if (startingPoint != m_cache.get<byFullName>().begin()) {
+    BOOST_ASSERT((*startingPoint)->getFullName() < interest.getName());
+  }
 
   bool hasLeftmostSelector = (interest.getChildSelector() <= 0);
   bool hasRightmostSelector = !hasLeftmostSelector;
 
   // filter out "stale" data
-  if (interest.getMustBeFresh())
+  if (interest.getMustBeFresh()) {
     startingPoint = findNextFresh(startingPoint);
+  }
 
   if (startingPoint == m_cache.get<byFullName>().end()) {
     return nullptr;
   }
 
-  if (hasLeftmostSelector)
-    {
-      if (interest.matchesData((*startingPoint)->getData()))
-        {
-          return *startingPoint;
-        }
+  if (hasLeftmostSelector) {
+    if (interest.matchesData((*startingPoint)->getData())) {
+      return *startingPoint;
     }
+  }
 
-  //iterate to the right
-  Cache::index<byFullName>::type::iterator rightmost = startingPoint;
-  if (startingPoint != m_cache.get<byFullName>().end())
-    {
-      Cache::index<byFullName>::type::iterator rightmostCandidate = startingPoint;
-      Name currentChildPrefix("");
+  // iterate to the right
+  auto rightmost = startingPoint;
+  if (startingPoint != m_cache.get<byFullName>().end()) {
+    auto rightmostCandidate = startingPoint;
+    Name currentChildPrefix("");
 
-      while (true)
-        {
-          ++rightmostCandidate;
-          // filter out "stale" data
-          if (interest.getMustBeFresh())
-            rightmostCandidate = findNextFresh(rightmostCandidate);
+    while (true) {
+      ++rightmostCandidate;
+      // filter out "stale" data
+      if (interest.getMustBeFresh()) {
+        rightmostCandidate = findNextFresh(rightmostCandidate);
+      }
 
-          bool isInBoundaries = (rightmostCandidate != m_cache.get<byFullName>().end());
-          bool isInPrefix = false;
-          if (isInBoundaries)
-            {
-              isInPrefix = interest.getName().isPrefixOf((*rightmostCandidate)->getFullName());
+      bool isInBoundaries = (rightmostCandidate != m_cache.get<byFullName>().end());
+      bool isInPrefix = false;
+      if (isInBoundaries) {
+        isInPrefix = interest.getName().isPrefixOf((*rightmostCandidate)->getFullName());
+      }
+
+      if (isInPrefix) {
+        if (interest.matchesData((*rightmostCandidate)->getData())) {
+          if (hasLeftmostSelector) {
+            return *rightmostCandidate;
+          }
+
+          if (hasRightmostSelector) {
+            // get prefix which is one component longer than Interest name
+            const Name& childPrefix = (*rightmostCandidate)->getFullName().getPrefix(interest.getName().size() + 1);
+            if (currentChildPrefix.empty() || (childPrefix != currentChildPrefix)) {
+              currentChildPrefix = childPrefix;
+              rightmost = rightmostCandidate;
             }
-
-          if (isInPrefix)
-            {
-              if (interest.matchesData((*rightmostCandidate)->getData()))
-                {
-                  if (hasLeftmostSelector)
-                    {
-                      return *rightmostCandidate;
-                    }
-
-                  if (hasRightmostSelector)
-                    {
-                      // get prefix which is one component longer than Interest name
-                      const Name& childPrefix = (*rightmostCandidate)->getFullName()
-                                                  .getPrefix(interest.getName().size() + 1);
-
-                      if (currentChildPrefix.empty() || (childPrefix != currentChildPrefix))
-                        {
-                          currentChildPrefix = childPrefix;
-                          rightmost = rightmostCandidate;
-                        }
-                    }
-                }
-            }
-          else
-            break;
+          }
         }
+      }
+      else {
+        break;
+      }
     }
+  }
 
-  if (rightmost != startingPoint)
-    {
-      return *rightmost;
+  if (rightmost != startingPoint) {
+    return *rightmost;
+  }
+
+  if (hasRightmostSelector) { // if rightmost was not found, try starting point
+    if (interest.matchesData((*startingPoint)->getData())) {
+      return *startingPoint;
     }
+  }
 
-  if (hasRightmostSelector) // if rightmost was not found, try starting point
-    {
-      if (interest.matchesData((*startingPoint)->getData()))
-        {
-          return *startingPoint;
-        }
-    }
-
-  return 0;
+  return nullptr;
 }
 
 InMemoryStorage::Cache::iterator
 InMemoryStorage::freeEntry(Cache::iterator it)
 {
-  //push the *empty* entry into mem pool
+  // push the *empty* entry into mem pool
   (*it)->release();
   m_freeEntries.push(*it);
   m_nPackets--;
@@ -371,21 +356,19 @@
 InMemoryStorage::erase(const Name& prefix, const bool isPrefix)
 {
   if (isPrefix) {
-    Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().lower_bound(prefix);
-
+    auto it = m_cache.get<byFullName>().lower_bound(prefix);
     while (it != m_cache.get<byFullName>().end() && prefix.isPrefixOf((*it)->getName())) {
-      //let derived class do something with the entry
+      // let derived class do something with the entry
       beforeErase(*it);
       it = freeEntry(it);
     }
   }
   else {
-    Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().find(prefix);
-
+    auto it = m_cache.get<byFullName>().find(prefix);
     if (it == m_cache.get<byFullName>().end())
       return;
 
-    //let derived class do something with the entry
+    // let derived class do something with the entry
     beforeErase(*it);
     freeEntry(it);
   }
@@ -397,8 +380,7 @@
 void
 InMemoryStorage::eraseImpl(const Name& name)
 {
-  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().find(name);
-
+  auto it = m_cache.get<byFullName>().find(name);
   if (it == m_cache.get<byFullName>().end())
     return;
 
@@ -408,16 +390,14 @@
 InMemoryStorage::const_iterator
 InMemoryStorage::begin() const
 {
-  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().begin();
-
+  auto it = m_cache.get<byFullName>().begin();
   return const_iterator(&((*it)->getData()), &m_cache, it);
 }
 
 InMemoryStorage::const_iterator
 InMemoryStorage::end() const
 {
-  Cache::index<byFullName>::type::iterator it = m_cache.get<byFullName>().end();
-
+  auto it = m_cache.get<byFullName>().end();
   return const_iterator(nullptr, &m_cache, it);
 }
 
@@ -439,11 +419,9 @@
 void
 InMemoryStorage::printCache(std::ostream& os) const
 {
-  //start from the upper layer towards bottom
-  const Cache::index<byFullName>::type& cacheIndex = m_cache.get<byFullName>();
-  for (Cache::index<byFullName>::type::iterator it = cacheIndex.begin();
-       it != cacheIndex.end(); it++)
-    os << (*it)->getFullName() << std::endl;
+  // start from the upper layer towards bottom
+  for (const auto& elem : m_cache.get<byFullName>())
+    os << elem->getFullName() << std::endl;
 }
 
 } // namespace ndn
diff --git a/src/ims/in-memory-storage.hpp b/src/ims/in-memory-storage.hpp
index 9e61e7a..ae92916 100644
--- a/src/ims/in-memory-storage.hpp
+++ b/src/ims/in-memory-storage.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -63,9 +63,15 @@
    *
    *  @note Don't try to instantiate this class directly, use InMemoryStorage::begin() instead.
    */
-  class const_iterator : public std::iterator<std::input_iterator_tag, const Data>
+  class const_iterator
   {
   public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type        = const Data;
+    using difference_type   = std::ptrdiff_t;
+    using pointer           = value_type*;
+    using reference         = value_type&;
+
     const_iterator(const Data* ptr, const Cache* cache,
                    Cache::index<byFullName>::type::iterator it);
 
@@ -75,10 +81,10 @@
     const_iterator
     operator++(int);
 
-    const Data&
+    reference
     operator*();
 
-    const Data*
+    pointer
     operator->();
 
     bool
diff --git a/src/meta-info.cpp b/src/meta-info.cpp
index c6a43a4..f46784c 100644
--- a/src/meta-info.cpp
+++ b/src/meta-info.cpp
@@ -88,10 +88,9 @@
 MetaInfo&
 MetaInfo::setAppMetaInfo(const std::list<Block>& info)
 {
-  for (std::list<Block>::const_iterator i = info.begin(); i != info.end(); ++i) {
-    if (!(128 <= i->type() && i->type() <= 252))
-      BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range "
-                                  "[128, 252]"));
+  for (const auto& block : info) {
+    if (block.type() < 128 || block.type() > 252)
+      BOOST_THROW_EXCEPTION(Error("AppMetaInfo block has type outside the application range [128, 252]"));
   }
 
   m_wire.reset();
@@ -114,11 +113,10 @@
 bool
 MetaInfo::removeAppMetaInfo(uint32_t tlvType)
 {
-  for (std::list<Block>::iterator iter = m_appMetaInfo.begin();
-       iter != m_appMetaInfo.end(); ++iter) {
-    if (iter->type() == tlvType) {
+  for (auto it = m_appMetaInfo.begin(); it != m_appMetaInfo.end(); ++it) {
+    if (it->type() == tlvType) {
       m_wire.reset();
-      m_appMetaInfo.erase(iter);
+      m_appMetaInfo.erase(it);
       return true;
     }
   }
@@ -128,13 +126,9 @@
 const Block*
 MetaInfo::findAppMetaInfo(uint32_t tlvType) const
 {
-  for (std::list<Block>::const_iterator iter = m_appMetaInfo.begin();
-       iter != m_appMetaInfo.end(); ++iter) {
-    if (iter->type() == tlvType) {
-      return &*iter;
-    }
-  }
-  return 0;
+  auto it = std::find_if(m_appMetaInfo.begin(), m_appMetaInfo.end(),
+                         [=] (const Block& b) { return b.type() == tlvType; });
+  return it != m_appMetaInfo.end() ? &*it : nullptr;
 }
 
 template<encoding::Tag TAG>
@@ -149,9 +143,8 @@
 
   size_t totalLength = 0;
 
-  for (std::list<Block>::const_reverse_iterator appMetaInfoItem = m_appMetaInfo.rbegin();
-       appMetaInfoItem != m_appMetaInfo.rend(); ++appMetaInfoItem) {
-    totalLength += encoder.prependBlock(*appMetaInfoItem);
+  for (auto it = m_appMetaInfo.rbegin(); it != m_appMetaInfo.rend(); ++it) {
+    totalLength += encoder.prependBlock(*it);
   }
 
   // FinalBlockId
@@ -161,7 +154,8 @@
 
   // FreshnessPeriod
   if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD) {
-    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod, m_freshnessPeriod.count());
+    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
+                                                  static_cast<uint64_t>(m_freshnessPeriod.count()));
   }
 
   // ContentType
@@ -204,8 +198,7 @@
   //                FinalBlockId?
   //                AppMetaInfo*
 
-
-  Block::element_const_iterator val = m_wire.elements_begin();
+  auto val = m_wire.elements_begin();
 
   // ContentType
   if (val != m_wire.elements_end() && val->type() == tlv::ContentType) {
@@ -247,7 +240,7 @@
   os << "ContentType: " << info.getType();
 
   // FreshnessPeriod
-  if (info.getFreshnessPeriod() > time::milliseconds::zero()) {
+  if (info.getFreshnessPeriod() > 0_ms) {
     os << ", FreshnessPeriod: " << info.getFreshnessPeriod();
   }
 
@@ -258,9 +251,8 @@
   }
 
   // App-defined MetaInfo items
-  for (std::list<Block>::const_iterator iter = info.getAppMetaInfo().begin();
-       iter != info.getAppMetaInfo().end(); ++iter) {
-    os << ", AppMetaInfoTlvType: " << iter->type();
+  for (const auto& block : info.getAppMetaInfo()) {
+    os << ", AppMetaInfoTlvType: " << block.type();
   }
 
   return os;
diff --git a/src/mgmt/dispatcher.cpp b/src/mgmt/dispatcher.cpp
index 2a14a91..7352720 100644
--- a/src/mgmt/dispatcher.cpp
+++ b/src/mgmt/dispatcher.cpp
@@ -55,11 +55,8 @@
 Dispatcher::~Dispatcher()
 {
   std::vector<Name> topPrefixNames;
-  std::transform(m_topLevelPrefixes.begin(), m_topLevelPrefixes.end(),
-                 std::back_inserter(topPrefixNames),
-                 [] (const std::unordered_map<Name, TopPrefixEntry>::value_type& entry) {
-                   return entry.second.topPrefix;
-                 });
+  std::transform(m_topLevelPrefixes.begin(), m_topLevelPrefixes.end(), std::back_inserter(topPrefixNames),
+                 [] (const auto& entry) { return entry.second.topPrefix; });
 
   for (const auto& name : topPrefixNames) {
     removeTopPrefix(name);
@@ -71,7 +68,7 @@
                          const security::SigningInfo& signingInfo)
 {
   bool hasOverlap = std::any_of(m_topLevelPrefixes.begin(), m_topLevelPrefixes.end(),
-                                [&] (const std::unordered_map<Name, TopPrefixEntry>::value_type& x) {
+                                [&prefix] (const auto& x) {
                                   return x.first.isPrefixOf(prefix) || prefix.isPrefixOf(x.first);
                                 });
   if (hasOverlap) {
@@ -92,8 +89,8 @@
 
   for (const auto& entry : m_handlers) {
     Name fullPrefix = Name(prefix).append(entry.first);
-    const InterestFilterId* filter = m_face.setInterestFilter(fullPrefix, bind(entry.second, prefix, _2));
-    topPrefixEntry.interestFilters.push_back(filter);
+    const auto* filterId = m_face.setInterestFilter(fullPrefix, bind(entry.second, prefix, _2));
+    topPrefixEntry.interestFilters.push_back(filterId);
   }
 }
 
@@ -121,12 +118,12 @@
 {
   bool hasOverlapWithHandlers =
     std::any_of(m_handlers.begin(), m_handlers.end(),
-                [&] (const std::unordered_map<PartialName, InterestHandler>::value_type& entry) {
+                [&] (const auto& entry) {
                   return entry.first.isPrefixOf(relPrefix) || relPrefix.isPrefixOf(entry.first);
                 });
   bool hasOverlapWithStreams =
     std::any_of(m_streams.begin(), m_streams.end(),
-                [&] (const std::unordered_map<PartialName, uint64_t>::value_type& entry) {
+                [&] (const auto& entry) {
                   return entry.first.isPrefixOf(relPrefix) || relPrefix.isPrefixOf(entry.first);
                 });
 
@@ -210,8 +207,8 @@
     return;
   }
 
-  AcceptContinuation accept = bind(accepted, _1, prefix, interest, parameters);
-  RejectContinuation reject = bind(rejected, _1, interest);
+  AcceptContinuation accept = [=] (const auto& req) { accepted(req, prefix, interest, parameters); };
+  RejectContinuation reject = [=] (RejectReply reply) { rejected(reply, interest); };
   authorization(prefix, interest, parameters.get(), accept, reject);
 }
 
@@ -225,7 +222,7 @@
 {
   if (validateParams(*parameters)) {
     handler(prefix, interest, *parameters,
-            bind(&Dispatcher::sendControlResponse, this, _1, interest, false));
+            [=] (const auto& resp) { this->sendControlResponse(resp, interest); });
   }
   else {
     sendControlResponse(ControlResponse(400, "failed in validating parameters"), interest);
@@ -247,8 +244,8 @@
 
 void
 Dispatcher::addStatusDataset(const PartialName& relPrefix,
-                             const Authorization& authorization,
-                             const StatusDatasetHandler& handler)
+                             Authorization authorize,
+                             StatusDatasetHandler handle)
 {
   if (!m_topLevelPrefixes.empty()) {
     BOOST_THROW_EXCEPTION(std::domain_error("one or more top-level prefix has been added"));
@@ -259,14 +256,17 @@
   }
 
   AuthorizationAcceptedCallback accepted =
-    bind(&Dispatcher::processAuthorizedStatusDatasetInterest, this, _1, _2, _3, handler);
+    bind(&Dispatcher::processAuthorizedStatusDatasetInterest, this, _1, _2, _3, std::move(handle));
   AuthorizationRejectedCallback rejected =
     bind(&Dispatcher::afterAuthorizationRejected, this, _1, _2);
 
   // follow the general path if storage is a miss
-  InterestHandler missContinuation = bind(&Dispatcher::processStatusDatasetInterest, this,
-                                          _1, _2, authorization, accepted, rejected);
-  m_handlers[relPrefix] = bind(&Dispatcher::queryStorage, this, _1, _2, missContinuation);
+  InterestHandler missContinuation = bind(&Dispatcher::processStatusDatasetInterest, this, _1, _2,
+                                          std::move(authorize), std::move(accepted), std::move(rejected));
+
+  m_handlers[relPrefix] = [this, miss = std::move(missContinuation)] (auto&&... args) {
+    this->queryStorage(std::forward<decltype(args)>(args)..., miss);
+  };
 }
 
 void
@@ -283,8 +283,8 @@
     return;
   }
 
-  AcceptContinuation accept = bind(accepted, _1, prefix, interest, nullptr);
-  RejectContinuation reject = bind(rejected, _1, interest);
+  AcceptContinuation accept = [=] (const auto& req) { accepted(req, prefix, interest, nullptr); };
+  RejectContinuation reject = [=] (RejectReply reply) { rejected(reply, interest); };
   authorization(prefix, interest, nullptr, accept, reject);
 }
 
@@ -332,10 +332,12 @@
 
   // register a handler for the subscriber of this notification stream
   // keep silent if Interest does not match a stored notification
-  m_handlers[relPrefix] = bind(&Dispatcher::queryStorage, this, _1, _2, nullptr);
+  m_handlers[relPrefix] = [this] (auto&&... args) {
+    this->queryStorage(std::forward<decltype(args)>(args)..., nullptr);
+  };
   m_streams[relPrefix] = 0;
 
-  return bind(&Dispatcher::postNotification, this, _1, relPrefix);
+  return [=] (const Block& b) { postNotification(b, relPrefix); };
 }
 
 void
diff --git a/src/mgmt/dispatcher.hpp b/src/mgmt/dispatcher.hpp
index 4845b54..6eca613 100644
--- a/src/mgmt/dispatcher.hpp
+++ b/src/mgmt/dispatcher.hpp
@@ -186,9 +186,9 @@
    *  \param relPrefix a prefix for this command, e.g., "faces/create";
    *                   relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be
    *                   non-overlapping (no relPrefix is a prefix of another relPrefix)
-   *  \param authorization Callback to authorize the incoming commands
-   *  \param validateParams Callback to validate parameters of the incoming commands
-   *  \param handler Callback to handle the commands
+   *  \param authorize Callback to authorize the incoming commands
+   *  \param validate Callback to validate parameters of the incoming commands
+   *  \param handle Callback to handle the commands
    *  \pre no top-level prefix has been added
    *  \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix
    *  \throw std::domain_error one or more top-level prefix has been added
@@ -209,17 +209,17 @@
   template<typename CP>
   void
   addControlCommand(const PartialName& relPrefix,
-                    const Authorization& authorization,
-                    const ValidateParameters& validateParams,
-                    const ControlCommandHandler& handler);
+                    Authorization authorize,
+                    ValidateParameters validate,
+                    ControlCommandHandler handle);
 
 public: // StatusDataset
   /** \brief register a StatusDataset or a prefix under which StatusDatasets can be requested
    *  \param relPrefix a prefix for this dataset, e.g., "faces/list";
    *                   relPrefixes in ControlCommands, StatusDatasets, NotificationStreams must be
    *                   non-overlapping (no relPrefix is a prefix of another relPrefix)
-   *  \param authorization should set identity to Name() if the dataset is public
-   *  \param handler Callback to process the incoming dataset requests
+   *  \param authorize should set identity to Name() if the dataset is public
+   *  \param handle Callback to process the incoming dataset requests
    *  \pre no top-level prefix has been added
    *  \throw std::out_of_range \p relPrefix overlaps with an existing relPrefix
    *  \throw std::domain_error one or more top-level prefix has been added
@@ -246,8 +246,8 @@
    */
   void
   addStatusDataset(const PartialName& relPrefix,
-                   const Authorization& authorization,
-                   const StatusDatasetHandler& handler);
+                   Authorization authorize,
+                   StatusDatasetHandler handle);
 
 public: // NotificationStream
   /** \brief register a NotificationStream
@@ -440,7 +440,7 @@
   struct TopPrefixEntry
   {
     Name topPrefix;
-    optional<const RegisteredPrefixId*> registeredPrefixId = nullopt;
+    optional<const RegisteredPrefixId*> registeredPrefixId;
     std::vector<const InterestFilterId*> interestFilters;
   };
   std::unordered_map<Name, TopPrefixEntry> m_topLevelPrefixes;
@@ -461,9 +461,9 @@
 template<typename CP>
 void
 Dispatcher::addControlCommand(const PartialName& relPrefix,
-                              const Authorization& authorization,
-                              const ValidateParameters& validateParams,
-                              const ControlCommandHandler& handler)
+                              Authorization authorize,
+                              ValidateParameters validate,
+                              ControlCommandHandler handle)
 {
   if (!m_topLevelPrefixes.empty()) {
     BOOST_THROW_EXCEPTION(std::domain_error("one or more top-level prefix has been added"));
@@ -473,19 +473,20 @@
     BOOST_THROW_EXCEPTION(std::out_of_range("relPrefix overlaps with another relPrefix"));
   }
 
-  ControlParametersParser parser = [] (const name::Component& comp) -> shared_ptr<ControlParameters> {
+  auto parser = [] (const name::Component& comp) -> shared_ptr<ControlParameters> {
     return make_shared<CP>(comp.blockFromValue());
   };
 
   AuthorizationAcceptedCallback accepted =
     bind(&Dispatcher::processAuthorizedControlCommandInterest, this,
-         _1, _2, _3, _4, validateParams, handler);
+         _1, _2, _3, _4, std::move(validate), std::move(handle));
 
   AuthorizationRejectedCallback rejected =
     bind(&Dispatcher::afterAuthorizationRejected, this, _1, _2);
 
   m_handlers[relPrefix] = bind(&Dispatcher::processControlCommandInterest, this,
-                               _1, relPrefix, _2, parser, authorization, accepted, rejected);
+                               _1, relPrefix, _2, std::move(parser), std::move(authorize),
+                               std::move(accepted), std::move(rejected));
 }
 
 } // namespace mgmt
diff --git a/src/mgmt/nfd/controller.hpp b/src/mgmt/nfd/controller.hpp
index 6582a66..aeb4692 100644
--- a/src/mgmt/nfd/controller.hpp
+++ b/src/mgmt/nfd/controller.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -74,7 +74,7 @@
   start(const ControlParameters& parameters,
         const CommandSucceedCallback& onSuccess,
         const CommandFailCallback& onFailure,
-        const CommandOptions& options = CommandOptions())
+        const CommandOptions& options = {})
   {
     shared_ptr<ControlCommand> command = make_shared<Command>();
     this->startCommand(command, parameters, onSuccess, onFailure, options);
@@ -83,10 +83,10 @@
   /** \brief start dataset fetching
    */
   template<typename Dataset>
-  typename std::enable_if<std::is_default_constructible<Dataset>::value>::type
+  std::enable_if_t<std::is_default_constructible<Dataset>::value>
   fetch(const std::function<void(typename Dataset::ResultType)>& onSuccess,
         const DatasetFailCallback& onFailure,
-        const CommandOptions& options = CommandOptions())
+        const CommandOptions& options = {})
   {
     this->fetchDataset(make_shared<Dataset>(), onSuccess, onFailure, options);
   }
@@ -98,7 +98,7 @@
   fetch(const ParamType& param,
         const std::function<void(typename Dataset::ResultType)>& onSuccess,
         const DatasetFailCallback& onFailure,
-        const CommandOptions& options = CommandOptions())
+        const CommandOptions& options = {})
   {
     this->fetchDataset(make_shared<Dataset>(param), onSuccess, onFailure, options);
   }
diff --git a/src/net/detail/network-monitor-impl-osx.cpp b/src/net/detail/network-monitor-impl-osx.cpp
index 7af5337..839faaa 100644
--- a/src/net/detail/network-monitor-impl-osx.cpp
+++ b/src/net/detail/network-monitor-impl-osx.cpp
@@ -79,8 +79,7 @@
   IfAddrs()
   {
     if (::getifaddrs(&m_ifaList) < 0) {
-      BOOST_THROW_EXCEPTION(NetworkMonitorImplOsx::Error(std::string("getifaddrs() failed: ") +
-                                                         strerror(errno)));
+      BOOST_THROW_EXCEPTION(NetworkMonitorImplOsx::Error("getifaddrs() failed: "s + strerror(errno)));
     }
   }
 
diff --git a/src/net/detail/network-monitor-impl-rtnl.cpp b/src/net/detail/network-monitor-impl-rtnl.cpp
index 02c84fb..ab797db 100644
--- a/src/net/detail/network-monitor-impl-rtnl.cpp
+++ b/src/net/detail/network-monitor-impl-rtnl.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -96,8 +96,7 @@
 
   int fd = ::socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
   if (fd < 0) {
-    BOOST_THROW_EXCEPTION(Error(std::string("Cannot create netlink socket (") +
-                                std::strerror(errno) + ")"));
+    BOOST_THROW_EXCEPTION(Error("Cannot create netlink socket ("s + std::strerror(errno) + ")"));
   }
   m_socket->assign(fd);
 
@@ -107,15 +106,13 @@
                    RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
                    RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
   if (::bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
-    BOOST_THROW_EXCEPTION(Error(std::string("Cannot bind netlink socket (") +
-                                std::strerror(errno) + ")"));
+    BOOST_THROW_EXCEPTION(Error("Cannot bind netlink socket ("s + std::strerror(errno) + ")"));
   }
 
   // find out what pid has been assigned to us
   socklen_t len = sizeof(addr);
   if (::getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) < 0) {
-    BOOST_THROW_EXCEPTION(Error(std::string("Cannot obtain netlink socket address (") +
-                                std::strerror(errno) + ")"));
+    BOOST_THROW_EXCEPTION(Error("Cannot obtain netlink socket address ("s + std::strerror(errno) + ")"));
   }
   if (len != sizeof(addr)) {
     BOOST_THROW_EXCEPTION(Error("Wrong address length (" + to_string(len) + ")"));
diff --git a/src/net/dns.cpp b/src/net/dns.cpp
index 0043ec9..1204451 100644
--- a/src/net/dns.cpp
+++ b/src/net/dns.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -57,7 +57,7 @@
 
     m_resolver.async_resolve(q, bind(&Resolver::onResolveResult, this, _1, _2, self));
 
-    m_resolveTimeout = m_scheduler.scheduleEvent(timeout, bind(&Resolver::onResolveTimeout, this, self));
+    m_resolveTimeout = m_scheduler.scheduleEvent(timeout, [=] { onResolveTimeout(self); });
   }
 
   iterator
@@ -73,7 +73,7 @@
   {
     m_scheduler.cancelEvent(m_resolveTimeout);
     // ensure the Resolver isn't destructed while callbacks are still pending, see #2653
-    m_resolver.get_io_service().post(bind([] (const shared_ptr<Resolver>&) {}, self));
+    m_resolver.get_io_service().post([self] {});
 
     if (error) {
       if (error == boost::asio::error::operation_aborted)
@@ -100,7 +100,7 @@
   {
     m_resolver.cancel();
     // ensure the Resolver isn't destructed while callbacks are still pending, see #2653
-    m_resolver.get_io_service().post(bind([] (const shared_ptr<Resolver>&) {}, self));
+    m_resolver.get_io_service().post([self] {});
 
     if (m_onError)
       m_onError("Hostname resolution timed out");
diff --git a/src/net/face-uri.cpp b/src/net/face-uri.cpp
index ceed453..dc70760 100644
--- a/src/net/face-uri.cpp
+++ b/src/net/face-uri.cpp
@@ -656,11 +656,9 @@
     return;
   }
 
-  static CanonizeSuccessCallback successNop = bind([]{});
-  static CanonizeFailureCallback failureNop = bind([]{});
   cp->canonize(*this,
-               onSuccess ? onSuccess : successNop,
-               onFailure ? onFailure : failureNop,
+               onSuccess ? onSuccess : [] (auto&&) {},
+               onFailure ? onFailure : [] (auto&&) {},
                io, timeout);
 }
 
diff --git a/src/security/pib/certificate-container.hpp b/src/security/pib/certificate-container.hpp
index cc1798a..1fb1c63 100644
--- a/src/security/pib/certificate-container.hpp
+++ b/src/security/pib/certificate-container.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -24,6 +24,7 @@
 
 #include "../v2/certificate.hpp"
 
+#include <iterator>
 #include <set>
 #include <unordered_map>
 
@@ -46,9 +47,15 @@
 class CertificateContainer : noncopyable
 {
 public:
-  class const_iterator : public std::iterator<std::forward_iterator_tag, const v2::Certificate>
+  class const_iterator
   {
   public:
+    using iterator_category = std::forward_iterator_tag;
+    using value_type        = const v2::Certificate;
+    using difference_type   = std::ptrdiff_t;
+    using pointer           = value_type*;
+    using reference         = value_type&;
+
     const_iterator();
 
     v2::Certificate
diff --git a/src/security/pib/identity-container.hpp b/src/security/pib/identity-container.hpp
index 9e45cf9..24bd5c3 100644
--- a/src/security/pib/identity-container.hpp
+++ b/src/security/pib/identity-container.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -24,6 +24,7 @@
 
 #include "identity.hpp"
 
+#include <iterator>
 #include <set>
 #include <unordered_map>
 
@@ -46,9 +47,15 @@
 class IdentityContainer : noncopyable
 {
 public:
-  class const_iterator : public std::iterator<std::forward_iterator_tag, const Identity>
+  class const_iterator
   {
   public:
+    using iterator_category = std::forward_iterator_tag;
+    using value_type        = const Identity;
+    using difference_type   = std::ptrdiff_t;
+    using pointer           = value_type*;
+    using reference         = value_type&;
+
     const_iterator();
 
     Identity
diff --git a/src/security/pib/key-container.hpp b/src/security/pib/key-container.hpp
index 55a799e..6475cd2 100644
--- a/src/security/pib/key-container.hpp
+++ b/src/security/pib/key-container.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -24,6 +24,7 @@
 
 #include "key.hpp"
 
+#include <iterator>
 #include <set>
 #include <unordered_map>
 
@@ -47,9 +48,15 @@
 class KeyContainer : noncopyable
 {
 public:
-  class const_iterator : public std::iterator<std::forward_iterator_tag, const Key>
+  class const_iterator
   {
   public:
+    using iterator_category = std::forward_iterator_tag;
+    using value_type        = const Key;
+    using difference_type   = std::ptrdiff_t;
+    using pointer           = value_type*;
+    using reference         = value_type&;
+
     const_iterator();
 
     Key
diff --git a/src/security/tpm/back-end-file.cpp b/src/security/tpm/back-end-file.cpp
index 7c836d2..a560fad 100644
--- a/src/security/tpm/back-end-file.cpp
+++ b/src/security/tpm/back-end-file.cpp
@@ -129,7 +129,7 @@
     return keyHandle;
   }
   catch (const std::runtime_error& e) {
-    BOOST_THROW_EXCEPTION(Error(std::string("Cannot write key to disk: ") + e.what()));
+    BOOST_THROW_EXCEPTION(Error("Cannot write key to disk: "s + e.what()));
   }
 }
 
diff --git a/src/security/tpm/back-end-mem.cpp b/src/security/tpm/back-end-mem.cpp
index 9d051c6..2427229 100644
--- a/src/security/tpm/back-end-mem.cpp
+++ b/src/security/tpm/back-end-mem.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,6 +23,7 @@
 #include "key-handle-mem.hpp"
 #include "../transform/private-key.hpp"
 #include "../../encoding/buffer-stream.hpp"
+
 #include <unordered_map>
 
 namespace ndn {
@@ -101,7 +102,7 @@
     m_impl->keys[keyName] = key;
   }
   catch (const PrivateKey::Error& e) {
-    BOOST_THROW_EXCEPTION(Error(std::string("Cannot import private key: ") + e.what()));
+    BOOST_THROW_EXCEPTION(Error("Cannot import private key: "s + e.what()));
   }
 }
 
diff --git a/src/security/v2/validation-policy-config.cpp b/src/security/v2/validation-policy-config.cpp
index f6f6ed6..2d82079 100644
--- a/src/security/v2/validation-policy-config.cpp
+++ b/src/security/v2/validation-policy-config.cpp
@@ -227,7 +227,7 @@
     case 's':
       return time::seconds(refreshPeriod);
     default:
-      BOOST_THROW_EXCEPTION(Error(std::string("Bad refresh time unit: ") + unit));
+      BOOST_THROW_EXCEPTION(Error("Bad refresh time unit: "s + unit));
   }
 }
 
diff --git a/src/util/backports-ostream-joiner.hpp b/src/util/backports-ostream-joiner.hpp
index 1ba1380..b52bac6 100644
--- a/src/util/backports-ostream-joiner.hpp
+++ b/src/util/backports-ostream-joiner.hpp
@@ -113,7 +113,7 @@
 };
 
 template<typename CharT, typename Traits, typename DelimT>
-inline ostream_joiner<typename std::decay<DelimT>::type, CharT, Traits>
+inline ostream_joiner<std::decay_t<DelimT>, CharT, Traits>
 make_ostream_joiner(std::basic_ostream<CharT, Traits>& os, DelimT&& delimiter)
 {
   return {os, std::forward<DelimT>(delimiter)};
diff --git a/src/util/logging.cpp b/src/util/logging.cpp
index 0e68092..9513bfb 100644
--- a/src/util/logging.cpp
+++ b/src/util/logging.cpp
@@ -52,7 +52,7 @@
 
 Logging::Logging()
 {
-  this->setDestinationImpl(shared_ptr<std::ostream>(&std::clog, bind([]{})));
+  this->setDestinationImpl(shared_ptr<std::ostream>(&std::clog, [] (auto) {}));
 
   const char* environ = std::getenv("NDN_LOG");
   if (environ != nullptr) {
@@ -202,7 +202,7 @@
 void
 Logging::setDestination(std::ostream& os)
 {
-  setDestination(shared_ptr<std::ostream>(&os, bind([]{})));
+  setDestination(shared_ptr<std::ostream>(&os, [] (auto) {}));
 }
 
 void
@@ -214,7 +214,7 @@
 
   auto backend = boost::make_shared<boost::log::sinks::text_ostream_backend>();
   backend->auto_flush(true);
-  backend->add_stream(boost::shared_ptr<std::ostream>(m_destination.get(), bind([]{})));
+  backend->add_stream(boost::shared_ptr<std::ostream>(m_destination.get(), [] (auto) {}));
 
   if (m_sink != nullptr) {
     boost::log::core::get()->remove_sink(m_sink);
diff --git a/src/util/notification-subscriber.cpp b/src/util/notification-subscriber.cpp
index 66ffd8c..e69800a 100644
--- a/src/util/notification-subscriber.cpp
+++ b/src/util/notification-subscriber.cpp
@@ -43,6 +43,7 @@
   , m_attempts(1)
   , m_scheduler(face.getIoService())
   , m_nackEvent(m_scheduler)
+  , m_lastInterestId(nullptr)
   , m_interestLifetime(interestLifetime)
 {
 }
@@ -56,7 +57,7 @@
     return;
   m_isRunning = true;
 
-  this->sendInitialInterest();
+  sendInitialInterest();
 }
 
 void
@@ -66,15 +67,15 @@
     return;
   m_isRunning = false;
 
-  if (m_lastInterestId != 0)
+  if (m_lastInterestId != nullptr)
     m_face.removePendingInterest(m_lastInterestId);
-  m_lastInterestId = 0;
+  m_lastInterestId = nullptr;
 }
 
 void
 NotificationSubscriberBase::sendInitialInterest()
 {
-  if (this->shouldStop())
+  if (shouldStop())
     return;
 
   auto interest = make_shared<Interest>(m_prefix);
@@ -83,15 +84,15 @@
   interest->setInterestLifetime(getInterestLifetime());
 
   m_lastInterestId = m_face.expressInterest(*interest,
-                       bind(&NotificationSubscriberBase::afterReceiveData, this, _2),
-                       bind(&NotificationSubscriberBase::afterReceiveNack, this, _2),
-                       bind(&NotificationSubscriberBase::afterTimeout, this));
+                                            [this] (const auto&, const auto& d) { this->afterReceiveData(d); },
+                                            [this] (const auto&, const auto& n) { this->afterReceiveNack(n); },
+                                            [this] (const auto&) { this->afterTimeout(); });
 }
 
 void
 NotificationSubscriberBase::sendNextInterest()
 {
-  if (this->shouldStop())
+  if (shouldStop())
     return;
 
   BOOST_ASSERT(m_lastSequenceNo != std::numeric_limits<uint64_t>::max()); // overflow or missing initial reply
@@ -103,9 +104,9 @@
   interest->setInterestLifetime(getInterestLifetime());
 
   m_lastInterestId = m_face.expressInterest(*interest,
-                       bind(&NotificationSubscriberBase::afterReceiveData, this, _2),
-                       bind(&NotificationSubscriberBase::afterReceiveNack, this, _2),
-                       bind(&NotificationSubscriberBase::afterTimeout, this));
+                                            [this] (const auto&, const auto& d) { this->afterReceiveData(d); },
+                                            [this] (const auto&, const auto& n) { this->afterReceiveNack(n); },
+                                            [this] (const auto&) { this->afterTimeout(); });
 }
 
 bool
@@ -113,8 +114,9 @@
 {
   if (!m_isRunning)
     return true;
-  if (!this->hasSubscriber() && onNack.isEmpty()) {
-    this->stop();
+
+  if (!hasSubscriber() && onNack.isEmpty()) {
+    stop();
     return true;
   }
   return false;
@@ -123,55 +125,54 @@
 void
 NotificationSubscriberBase::afterReceiveData(const Data& data)
 {
-  if (this->shouldStop())
+  if (shouldStop())
     return;
 
   try {
     m_lastSequenceNo = data.getName().get(-1).toSequenceNumber();
   }
   catch (const tlv::Error&) {
-    this->onDecodeError(data);
-    this->sendInitialInterest();
+    onDecodeError(data);
+    sendInitialInterest();
     return;
   }
 
-  if (!this->decodeAndDeliver(data)) {
-    this->onDecodeError(data);
-    this->sendInitialInterest();
+  if (!decodeAndDeliver(data)) {
+    onDecodeError(data);
+    sendInitialInterest();
     return;
   }
 
-  this->sendNextInterest();
+  sendNextInterest();
 }
 
 void
 NotificationSubscriberBase::afterReceiveNack(const lp::Nack& nack)
 {
-  if (this->shouldStop())
+  if (shouldStop())
     return;
 
-  this->onNack(nack);
+  onNack(nack);
 
   time::milliseconds delay = exponentialBackoff(nack);
-  m_nackEvent = m_scheduler.scheduleEvent(delay, [this] {this->sendInitialInterest();});
+  m_nackEvent = m_scheduler.scheduleEvent(delay, [this] { sendInitialInterest(); });
 }
 
 void
 NotificationSubscriberBase::afterTimeout()
 {
-  if (this->shouldStop())
+  if (shouldStop())
     return;
 
-  this->onTimeout();
+  onTimeout();
 
-  this->sendInitialInterest();
+  sendInitialInterest();
 }
 
 time::milliseconds
 NotificationSubscriberBase::exponentialBackoff(lp::Nack nack)
 {
   uint64_t nackSequenceNo;
-
   try {
     nackSequenceNo = nack.getInterest().getName().get(-1).toSequenceNumber();
   }
diff --git a/src/util/regex/regex-top-matcher.cpp b/src/util/regex/regex-top-matcher.cpp
index 0c2ac9a..3514951 100644
--- a/src/util/regex/regex-top-matcher.cpp
+++ b/src/util/regex/regex-top-matcher.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -172,9 +172,9 @@
 {
   std::string regexStr("^");
 
-  for (auto it = name.begin(); it != name.end(); it++) {
+  for (const auto& i : name) {
     regexStr.append("<");
-    regexStr.append(convertSpecialChar(it->toUri()));
+    regexStr.append(convertSpecialChar(i.toUri()));
     regexStr.append(">");
   }
 
diff --git a/src/util/scheduler.cpp b/src/util/scheduler.cpp
index 167b6e0..aecf15a 100644
--- a/src/util/scheduler.cpp
+++ b/src/util/scheduler.cpp
@@ -41,7 +41,7 @@
   time::nanoseconds
   expiresFromNow() const
   {
-    return std::max(expireTime - time::steady_clock::now(), time::nanoseconds::zero());
+    return std::max(expireTime - time::steady_clock::now(), 0_ns);
   }
 
 public:
@@ -129,7 +129,7 @@
 {
   if (!m_queue.empty()) {
     m_timer->expires_from_now((*m_queue.begin())->expiresFromNow());
-    m_timer->async_wait(bind(&Scheduler::executeEvent, this, _1));
+    m_timer->async_wait([this] (const auto& error) { this->executeEvent(error); });
   }
 }
 
diff --git a/src/util/signal/signal.hpp b/src/util/signal/signal.hpp
index 8c76e13..6eab994 100644
--- a/src/util/signal/signal.hpp
+++ b/src/util/signal/signal.hpp
@@ -64,14 +64,14 @@
    *  \warning The handler is permitted to disconnect itself, but it must ensure its validity.
    */
   Connection
-  connect(const Handler& handler);
+  connect(Handler handler);
 
   /** \brief connects a single-shot handler to the signal
    *
    *  After the handler is executed once, it is automatically disconnected.
    */
   Connection
-  connectSingleShot(const Handler& handler);
+  connectSingleShot(Handler handler);
 
 private: // API for owner
   /** \retval true if there is no connection
@@ -162,23 +162,23 @@
 
 template<typename Owner, typename ...TArgs>
 Connection
-Signal<Owner, TArgs...>::connect(const Handler& handler)
+Signal<Owner, TArgs...>::connect(Handler handler)
 {
-  auto it = m_slots.insert(m_slots.end(), {handler, nullptr});
-  it->disconnect = make_shared<function<void()>>(bind(&Self::disconnect, this, it));
+  auto it = m_slots.insert(m_slots.end(), {std::move(handler), nullptr});
+  it->disconnect = make_shared<function<void()>>([=] { disconnect(it); });
 
   return signal::Connection(weak_ptr<function<void()>>(it->disconnect));
 }
 
 template<typename Owner, typename ...TArgs>
 Connection
-Signal<Owner, TArgs...>::connectSingleShot(const Handler& handler)
+Signal<Owner, TArgs...>::connectSingleShot(Handler handler)
 {
   auto it = m_slots.insert(m_slots.end(), {nullptr, nullptr});
-  it->disconnect = make_shared<function<void()>>(bind(&Self::disconnect, this, it));
+  it->disconnect = make_shared<function<void()>>([=] { disconnect(it); });
   signal::Connection conn(weak_ptr<function<void()>>(it->disconnect));
 
-  it->handler = [conn, handler] (const TArgs&... args) mutable {
+  it->handler = [conn, handler = std::move(handler)] (const TArgs&... args) mutable {
     handler(args...);
     conn.disconnect();
   };
diff --git a/src/util/string-helper.cpp b/src/util/string-helper.cpp
index 642b238..abfacbe 100644
--- a/src/util/string-helper.cpp
+++ b/src/util/string-helper.cpp
@@ -87,7 +87,7 @@
     tr::bufferSource(hexString) >> tr::hexDecode() >> tr::streamSink(os);
   }
   catch (const tr::Error& e) {
-    BOOST_THROW_EXCEPTION(StringHelperError(std::string("Conversion from hex failed: ") + e.what()));
+    BOOST_THROW_EXCEPTION(StringHelperError("Conversion from hex failed: "s + e.what()));
   }
 
   return os.buf();
diff --git a/src/util/time.hpp b/src/util/time.hpp
index 0d1250d..9d5f8bb 100644
--- a/src/util/time.hpp
+++ b/src/util/time.hpp
@@ -45,8 +45,7 @@
  *  \note The function does not participate in the overload resolution
  *        unless std::numeric_limits<Rep>::is_signed is true.
  */
-template<typename Rep, typename Period,
-         typename = typename std::enable_if<std::numeric_limits<Rep>::is_signed>::type>
+template<typename Rep, typename Period, typename = std::enable_if_t<std::numeric_limits<Rep>::is_signed>>
 constexpr duration<Rep, Period>
 abs(duration<Rep, Period> d)
 {