util: backport C++17 std::clamp

refs #3636

Change-Id: I04db89ed99424b1e35f7c4c611fd4c967d49ca46
diff --git a/src/util/backports.hpp b/src/util/backports.hpp
index 42597e9..072d1c7 100644
--- a/src/util/backports.hpp
+++ b/src/util/backports.hpp
@@ -1,12 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2015, Regents of the University of California,
- *                     Arizona Board of Regents,
- *                     Colorado State University,
- *                     University Pierre & Marie Curie, Sorbonne University,
- *                     Washington University in St. Louis,
- *                     Beijing Institute of Technology,
- *                     The University of Memphis.
+ * Copyright (c) 2015-2016 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -34,6 +28,8 @@
 #include <boost/lexical_cast.hpp>
 #endif
 
+#include <algorithm>
+
 namespace ndn {
 
 #if __cpp_lib_make_unique
@@ -58,6 +54,24 @@
 }
 #endif // NDN_CXX_HAVE_STD_TO_STRING
 
+#if __cpp_lib_clamp >= 201603
+using std::clamp;
+#else
+template<typename T, typename Compare>
+constexpr const T&
+clamp(const T& v, const T& lo, const T& hi, Compare comp)
+{
+  return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
+}
+
+template<typename T>
+constexpr const T&
+clamp(const T& v, const T& lo, const T& hi)
+{
+  return (v < lo) ? lo : (hi < v) ? hi : v;
+}
+#endif // __cpp_lib_clamp
+
 } // namespace ndn
 
 #endif // NDN_UTIL_BACKPORTS_HPP
diff --git a/tests/unit-tests/util/backports.t.cpp b/tests/unit-tests/util/backports.t.cpp
index 550651a..35cb8cc 100644
--- a/tests/unit-tests/util/backports.t.cpp
+++ b/tests/unit-tests/util/backports.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2013-2016 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -72,6 +72,27 @@
   BOOST_CHECK_EQUAL(ptr->m.value, 42);
 }
 
+BOOST_AUTO_TEST_CASE(Clamp)
+{
+  int x = clamp(5, 1, 10);
+  BOOST_CHECK_EQUAL(x, 5);
+
+  x = clamp(-5, 1, 10);
+  BOOST_CHECK_EQUAL(x, 1);
+
+  x = clamp(15, 1, 10);
+  BOOST_CHECK_EQUAL(x, 10);
+
+  x = clamp(5, 10, 1, std::greater<int>());
+  BOOST_CHECK_EQUAL(x, 5);
+
+  x = clamp(-5, 10, 1, std::greater<int>());
+  BOOST_CHECK_EQUAL(x, 1);
+
+  x = clamp(15, 10, 1, std::greater<int>());
+  BOOST_CHECK_EQUAL(x, 10);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 BOOST_AUTO_TEST_SUITE_END()