Use more C++17 features

Mainly structured bindings, inline variables, and class template
argument deduction, plus many more smaller things.

Change-Id: I810d17e0adb470426e4e30c898e03b3140ad052f
diff --git a/tools/ndn-autoconfig/main.cpp b/tools/ndn-autoconfig/main.cpp
index ecfad81..afedc38 100644
--- a/tools/ndn-autoconfig/main.cpp
+++ b/tools/ndn-autoconfig/main.cpp
@@ -46,9 +46,9 @@
 
 namespace po = boost::program_options;
 
-const time::nanoseconds DAEMON_INITIAL_DELAY = 100_ms;
-const time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL = 1_h;
-const time::nanoseconds NETMON_DAMPEN_PERIOD = 5_s;
+constexpr time::nanoseconds DAEMON_INITIAL_DELAY = 100_ms;
+constexpr time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL = 1_h;
+constexpr time::nanoseconds NETMON_DAMPEN_PERIOD = 5_s;
 
 static void
 usage(std::ostream& os,
diff --git a/tools/ndn-autoconfig/multicast-discovery.cpp b/tools/ndn-autoconfig/multicast-discovery.cpp
index 0a76b22..a9fbc88 100644
--- a/tools/ndn-autoconfig/multicast-discovery.cpp
+++ b/tools/ndn-autoconfig/multicast-discovery.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -36,9 +36,9 @@
 using nfd::ControlParameters;
 
 const Name HUB_DISCOVERY_PREFIX("/localhop/ndn-autoconf/hub");
-const uint64_t HUB_DISCOVERY_ROUTE_COST(1);
-const time::milliseconds HUB_DISCOVERY_ROUTE_EXPIRATION = 30_s;
-const time::milliseconds HUB_DISCOVERY_INTEREST_LIFETIME = 4_s;
+constexpr uint64_t HUB_DISCOVERY_ROUTE_COST(1);
+constexpr time::milliseconds HUB_DISCOVERY_ROUTE_EXPIRATION = 30_s;
+constexpr time::milliseconds HUB_DISCOVERY_INTEREST_LIFETIME = 4_s;
 
 MulticastDiscovery::MulticastDiscovery(Face& face, nfd::Controller& controller)
   : m_face(face)
diff --git a/tools/ndn-autoconfig/procedure.cpp b/tools/ndn-autoconfig/procedure.cpp
index b0896ec..cda39ad 100644
--- a/tools/ndn-autoconfig/procedure.cpp
+++ b/tools/ndn-autoconfig/procedure.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -36,10 +36,10 @@
 using nfd::ControlParameters;
 using nfd::ControlResponse;
 
-const time::nanoseconds FACEURI_CANONIZE_TIMEOUT = 4_s;
+constexpr time::nanoseconds FACEURI_CANONIZE_TIMEOUT = 4_s;
 const std::vector<Name> HUB_PREFIXES{"/", "/localhop/nfd"};
-const nfd::RouteOrigin HUB_ROUTE_ORIGIN = nfd::ROUTE_ORIGIN_AUTOCONF;
-const uint64_t HUB_ROUTE_COST = 100;
+constexpr nfd::RouteOrigin HUB_ROUTE_ORIGIN = nfd::ROUTE_ORIGIN_AUTOCONF;
+constexpr uint64_t HUB_ROUTE_COST = 100;
 
 Procedure::Procedure(Face& face, KeyChain& keyChain)
   : m_face(face)
diff --git a/tools/nfdc/command-arguments.hpp b/tools/nfdc/command-arguments.hpp
index 6e096d6..2ab30f2 100644
--- a/tools/nfdc/command-arguments.hpp
+++ b/tools/nfdc/command-arguments.hpp
@@ -27,7 +27,6 @@
 #define NFD_TOOLS_NFDC_COMMAND_ARGUMENTS_HPP
 
 #include "core/common.hpp"
-#include "status-report.hpp"
 
 #include <ndn-cxx/encoding/nfd-constants.hpp>
 
@@ -43,14 +42,14 @@
 
 /** \brief contains named command arguments
  */
-class CommandArguments : public std::map<std::string, std::any>
+class CommandArguments : public std::map<std::string, std::any, std::less<>>
 {
 public:
   /** \return the argument value, or nullopt if the argument is omitted on command line
    */
   template<typename T>
   std::optional<T>
-  getOptional(const std::string& key) const
+  getOptional(std::string_view key) const
   {
     auto i = find(key);
     return i == end() ? std::nullopt : std::make_optional(std::any_cast<T>(i->second));
@@ -60,7 +59,7 @@
    */
   template<typename T>
   T
-  get(const std::string& key, const T& defaultValue = T()) const
+  get(std::string_view key, const T& defaultValue = T()) const
   {
     return getOptional<T>(key).value_or(defaultValue);
   }
@@ -69,7 +68,7 @@
    *  \return the argument value, or boost::logic::indeterminate if the argument is omitted on command line
    */
   boost::logic::tribool
-  getTribool(const std::string& key) const
+  getTribool(std::string_view key) const
   {
     auto value = getOptional<bool>(key);
     return value ? boost::logic::tribool(*value) : boost::logic::indeterminate;
diff --git a/tools/nfdc/command-definition.cpp b/tools/nfdc/command-definition.cpp
index 3c450e1..7952e25 100644
--- a/tools/nfdc/command-definition.cpp
+++ b/tools/nfdc/command-definition.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "command-definition.hpp"
+#include "status-report.hpp"
 
 #include <ndn-cxx/util/logger.hpp>
 
@@ -93,7 +94,7 @@
   NDN_CXX_UNREACHABLE;
 }
 
-CommandDefinition::CommandDefinition(const std::string& noun, const std::string& verb)
+CommandDefinition::CommandDefinition(std::string_view noun, std::string_view verb)
   : m_noun(noun)
   , m_verb(verb)
 {
@@ -103,8 +104,8 @@
 
 CommandDefinition&
 CommandDefinition::addArg(const std::string& name, ArgValueType valueType,
-                        Required isRequired, Positional allowPositional,
-                        const std::string& metavar)
+                          Required isRequired, Positional allowPositional,
+                          const std::string& metavar)
 {
   bool isNew = m_args.emplace(name,
     Arg{name, valueType, static_cast<bool>(isRequired),
@@ -151,7 +152,7 @@
         const std::string& valueToken = tokens[++i];
         NDN_LOG_TRACE(arg.name << " has value " << valueToken);
         try {
-          ca[arg.name] = this->parseValue(arg.valueType, valueToken);
+          ca[arg.name] = parseValue(arg.valueType, valueToken);
         }
         catch (const std::exception& e) {
           NDN_LOG_TRACE(valueToken << " cannot be parsed as " << arg.valueType);
@@ -180,7 +181,7 @@
       }
 
       try {
-        ca[arg.name] = this->parseValue(arg.valueType, token);
+        ca[arg.name] = parseValue(arg.valueType, token);
         NDN_LOG_TRACE(token << " is parsed as value for " << arg.name);
         break;
       }
@@ -207,7 +208,7 @@
     ++positionalArgIndex;
   }
 
-  for (const std::string& argName : m_requiredArgs) {
+  for (const auto& argName : m_requiredArgs) {
     if (ca.count(argName) == 0) {
       NDN_THROW(Error(argName + ": required argument is missing"));
     }
@@ -241,7 +242,7 @@
 }
 
 std::any
-CommandDefinition::parseValue(ArgValueType valueType, const std::string& token) const
+CommandDefinition::parseValue(ArgValueType valueType, const std::string& token)
 {
   switch (valueType) {
     case ArgValueType::NONE:
diff --git a/tools/nfdc/command-definition.hpp b/tools/nfdc/command-definition.hpp
index dc5afed..8cd56d9 100644
--- a/tools/nfdc/command-definition.hpp
+++ b/tools/nfdc/command-definition.hpp
@@ -122,7 +122,8 @@
   YES = true  ///< argument can be specified as positional
 };
 
-/** \brief declares semantics of a command
+/**
+ * \brief Defines a command
  */
 class CommandDefinition
 {
@@ -133,17 +134,17 @@
     using std::invalid_argument::invalid_argument;
   };
 
-  CommandDefinition(const std::string& noun, const std::string& verb);
+  CommandDefinition(std::string_view noun, std::string_view verb);
 
   ~CommandDefinition();
 
-  const std::string
+  const std::string&
   getNoun() const
   {
     return m_noun;
   }
 
-  const std::string
+  const std::string&
   getVerb() const
   {
     return m_verb;
@@ -162,7 +163,7 @@
    *  \param title one-line description, written in lower case
    */
   CommandDefinition&
-  setTitle(const std::string& title)
+  setTitle(std::string_view title)
   {
     m_title = title;
     return *this;
@@ -191,12 +192,12 @@
   parse(const std::vector<std::string>& tokens, size_t start = 0) const;
 
 private:
-  std::any
-  parseValue(ArgValueType valueType, const std::string& token) const;
+  static std::any
+  parseValue(ArgValueType valueType, const std::string& token);
 
 private:
-  std::string m_noun;
-  std::string m_verb;
+  const std::string m_noun;
+  const std::string m_verb;
   std::string m_title;
 
   struct Arg
diff --git a/tools/nfdc/command-parser.cpp b/tools/nfdc/command-parser.cpp
index 0d59de2..69bc26a 100644
--- a/tools/nfdc/command-parser.cpp
+++ b/tools/nfdc/command-parser.cpp
@@ -94,7 +94,7 @@
 }
 
 std::vector<const CommandDefinition*>
-CommandParser::listCommands(const std::string& noun, ParseMode mode) const
+CommandParser::listCommands(std::string_view noun, ParseMode mode) const
 {
   std::vector<const CommandDefinition*> results;
   for (auto i : m_commandOrder) {
@@ -126,7 +126,7 @@
   NDN_LOG_TRACE("found command noun=" << def.getNoun() << " verb=" << def.getVerb());
 
   size_t nConsumed = std::min<size_t>(2, tokens.size());
-  return std::make_tuple(def.getNoun(), def.getVerb(), def.parse(tokens, nConsumed), i->second->execute);
+  return {def.getNoun(), def.getVerb(), def.parse(tokens, nConsumed), i->second->execute};
 }
 
 } // namespace nfdc
diff --git a/tools/nfdc/command-parser.hpp b/tools/nfdc/command-parser.hpp
index e0e10b0..f03027b 100644
--- a/tools/nfdc/command-parser.hpp
+++ b/tools/nfdc/command-parser.hpp
@@ -93,7 +93,7 @@
    *  \return commands in insertion order
    */
   std::vector<const CommandDefinition*>
-  listCommands(const std::string& noun, ParseMode mode) const;
+  listCommands(std::string_view noun, ParseMode mode) const;
 
   /** \brief parse a command line
    *  \param tokens command line
diff --git a/tools/nfdc/execute-command.hpp b/tools/nfdc/execute-command.hpp
index 2d8a716..0458fb1 100644
--- a/tools/nfdc/execute-command.hpp
+++ b/tools/nfdc/execute-command.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,7 @@
 #define NFD_TOOLS_NFDC_EXECUTE_COMMAND_HPP
 
 #include "command-arguments.hpp"
+
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/mgmt/nfd/command-options.hpp>
 #include <ndn-cxx/mgmt/nfd/controller.hpp>
@@ -46,7 +47,8 @@
 using ndn::nfd::ControlResponse;
 using ndn::nfd::Controller;
 
-/** \brief context for command execution
+/**
+ * \brief Context for command execution
  */
 class ExecuteContext
 {
@@ -72,8 +74,8 @@
   makeDatasetFailureHandler(const std::string& datasetName);
 
 public:
-  const std::string& noun;
-  const std::string& verb;
+  std::string_view noun;
+  std::string_view verb;
   const CommandArguments& args;
 
   int exitCode; ///< program exit code
@@ -82,13 +84,13 @@
 
   Face& face;
   KeyChain& keyChain;
-  ///\todo validator
   Controller& controller;
 };
 
-/** \brief a function to execute a command
+/**
+ * \brief A function to execute a command
  */
-using ExecuteCommand = std::function<void(ExecuteContext& ctx)>;
+using ExecuteCommand = std::function<void(ExecuteContext&)>;
 
 } // namespace nfdc
 } // namespace tools
diff --git a/tools/nfdc/find-face.cpp b/tools/nfdc/find-face.cpp
index 05e7eec..2240433 100644
--- a/tools/nfdc/find-face.cpp
+++ b/tools/nfdc/find-face.cpp
@@ -114,10 +114,7 @@
     return uri;
   }
 
-  std::optional<FaceUri> result;
-  std::string error;
-  std::tie(result, error) = nfdc::canonize(m_ctx, uri);
-
+  auto [result, error] = nfdc::canonize(m_ctx, uri);
   if (result) {
     // Canonization succeeded
     return result;
diff --git a/tools/nfdc/format-helpers.cpp b/tools/nfdc/format-helpers.cpp
index a207bf8..63f2417 100644
--- a/tools/nfdc/format-helpers.cpp
+++ b/tools/nfdc/format-helpers.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -128,14 +128,13 @@
   return os;
 }
 
-Separator::Separator(const std::string& first, const std::string& subsequent)
+Separator::Separator(std::string_view first, std::string_view subsequent)
   : m_first(first)
   , m_subsequent(subsequent)
-  , m_count(0)
 {
 }
 
-Separator::Separator(const std::string& subsequent)
+Separator::Separator(std::string_view subsequent)
   : Separator("", subsequent)
 {
 }
@@ -152,7 +151,6 @@
 ItemAttributes::ItemAttributes(bool wantMultiLine, int maxAttributeWidth)
   : m_wantMultiLine(wantMultiLine)
   , m_maxAttributeWidth(maxAttributeWidth)
-  , m_count(0)
 {
 }
 
diff --git a/tools/nfdc/format-helpers.hpp b/tools/nfdc/format-helpers.hpp
index 95f3310..4140ae2 100644
--- a/tools/nfdc/format-helpers.hpp
+++ b/tools/nfdc/format-helpers.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -102,10 +102,10 @@
 class Separator : noncopyable
 {
 public:
-  Separator(const std::string& first, const std::string& subsequent);
+  Separator(std::string_view first, std::string_view subsequent);
 
   explicit
-  Separator(const std::string& subsequent);
+  Separator(std::string_view subsequent);
 
   int
   getCount() const
@@ -114,9 +114,9 @@
   }
 
 private:
-  std::string m_first;
-  std::string m_subsequent;
-  int m_count;
+  const std::string m_first;
+  const std::string m_subsequent;
+  int m_count = 0;
 
   friend std::ostream& operator<<(std::ostream& os, Separator& sep);
 };
@@ -166,9 +166,9 @@
   end() const;
 
 private:
-  bool m_wantMultiLine;
-  int m_maxAttributeWidth;
-  int m_count;
+  const bool m_wantMultiLine;
+  const int m_maxAttributeWidth;
+  int m_count = 0;
 
   friend std::ostream& operator<<(std::ostream& os, const ItemAttributes::Attribute& attr);
 };
diff --git a/tools/nfdc/help.cpp b/tools/nfdc/help.cpp
index 3642a91..052d16c 100644
--- a/tools/nfdc/help.cpp
+++ b/tools/nfdc/help.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -38,10 +38,10 @@
 
 NDN_LOG_INIT(nfdc.Help);
 
-const int LIST_COMMAND_NAME_COLUMN_WIDTH = 16;
+constexpr int LIST_COMMAND_NAME_COLUMN_WIDTH = 16;
 
 void
-helpList(std::ostream& os, const CommandParser& parser, ParseMode mode, const std::string& noun)
+helpList(std::ostream& os, const CommandParser& parser, ParseMode mode, std::string_view noun)
 {
   os << "nfdc [-h|--help] [-V|--version] [-f|--batch <batch-file>] [<command> [<args>]]\n\n";
   if (noun.empty()) {
@@ -70,7 +70,7 @@
 static void
 helpCommand(const std::string& noun, const std::string& verb)
 {
-  std::string manpage = "nfdc-" + noun;
+  const std::string manpage = "nfdc-" + noun;
 
   ::execlp("man", "man", manpage.data(), nullptr);
   NDN_LOG_FATAL("Error opening man page for " << manpage << ": " << std::strerror(errno));
@@ -79,7 +79,7 @@
 int
 help(std::ostream& os, const CommandParser& parser, std::vector<std::string> args)
 {
-  const auto helpOpts = {"help", "--help", "-h"};
+  const auto helpOpts = {"help"sv, "--help"sv, "-h"sv};
   auto it = std::find_first_of(args.begin(), args.end(), helpOpts.begin(), helpOpts.end());
   if (it == args.end())
     return 2;
diff --git a/tools/nfdc/help.hpp b/tools/nfdc/help.hpp
index ccad718..53d21d4 100644
--- a/tools/nfdc/help.hpp
+++ b/tools/nfdc/help.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -40,7 +40,7 @@
  */
 void
 helpList(std::ostream& os, const CommandParser& parser,
-         ParseMode mode = ParseMode::ONE_SHOT, const std::string& noun = "");
+         ParseMode mode = ParseMode::ONE_SHOT, std::string_view noun = "");
 
 /** \brief tries to help the user, if requested on the command line
  *
diff --git a/tools/nfdc/main.cpp b/tools/nfdc/main.cpp
index ebe9d3c..a9d9c6f 100644
--- a/tools/nfdc/main.cpp
+++ b/tools/nfdc/main.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -62,15 +62,14 @@
 
   auto processLine = [&parser] (const std::vector<std::string>& line) -> Command {
     try {
-      Command cmd;
-      std::tie(cmd.noun, cmd.verb, cmd.ca, cmd.execute) = parser.parse(line, ParseMode::ONE_SHOT);
-      return cmd;
+      auto [noun, verb, ca, execute] = parser.parse(line, ParseMode::ONE_SHOT);
+      return {noun, verb, ca, execute};
     }
     catch (const std::invalid_argument& e) {
       int ret = help(std::cout, parser, line);
       if (ret == 2)
         std::cerr << e.what() << std::endl;
-      return {"", "", {}, nullptr};
+      return {};
     }
   };
 
@@ -83,7 +82,7 @@
       return 2;
     }
 
-    auto processIstream = [&commands,&processLine] (std::istream& is, const std::string& inputFile) {
+    auto processIstream = [&commands, &processLine] (std::istream& is, const std::string& inputFile) {
       std::string line;
       size_t lineCounter = 0;
       while (std::getline(is, line)) {
@@ -118,9 +117,8 @@
         }
 
         std::vector<std::string> lineArgs;
-        std::copy_if(firstNonEmptyToken, tokenizer.end(),
-                     std::back_inserter<std::vector<std::string>>(lineArgs),
-                     [] (const std::string& t) { return !t.empty(); });
+        std::copy_if(firstNonEmptyToken, tokenizer.end(), std::back_inserter(lineArgs),
+                     [] (const auto& t) { return !t.empty(); });
 
         auto cmd = processLine(lineArgs);
         if (cmd.noun.empty()) {
diff --git a/tools/nfdc/rib-module.cpp b/tools/nfdc/rib-module.cpp
index df980c4..5ed8553 100644
--- a/tools/nfdc/rib-module.cpp
+++ b/tools/nfdc/rib-module.cpp
@@ -203,9 +203,7 @@
       return;
     }
 
-    std::optional<FaceUri> canonized;
-    std::string error;
-    std::tie(canonized, error) = canonize(ctx, *faceUri);
+    auto [canonized, error] = canonize(ctx, *faceUri);
     if (!canonized) {
       // Canonization failed
       auto canonizationError = canonizeErrorHelper(*faceUri, error);