diff --git a/include/boost/program_options/config.hpp b/include/boost/program_options/config.hpp
index 8b7052174..e5b6d03d4 100644
--- a/include/boost/program_options/config.hpp
+++ b/include/boost/program_options/config.hpp
@@ -14,7 +14,7 @@
 #if BOOST_VERSION >= 103100   // works beginning from Boost V1.31.0
 
 ///////////////////////////////////////////////////////////////////////////////
-// enable automatic library variant selection 
+// enable automatic library variant selection
 #if !defined(BOOST_PROGRAM_OPTIONS_SOURCE) && !defined(BOOST_ALL_NO_LIB) && \
     !defined(BOOST_PROGRAM_OPTIONS_NO_LIB)
 
@@ -47,6 +47,4 @@
 #define BOOST_PROGRAM_OPTIONS_DECL
 #endif
 
-
 #endif // PROGRAM_OPTIONS_CONFIG_HK_2004_01_11
-
diff --git a/include/boost/program_options/variables_map.hpp b/include/boost/program_options/variables_map.hpp
index 362dedf28..9560db1d8 100644
--- a/include/boost/program_options/variables_map.hpp
+++ b/include/boost/program_options/variables_map.hpp
@@ -138,13 +138,24 @@ namespace boost { namespace program_options {
         const abstract_variables_map* m_next;
     };
 
+    namespace details
+    {
+        typedef
+        #if !defined(BOOST_PROGRAM_OPTIONS_NO_TRANSPARENT_COMPARATOR) && BOOST_CXX_VERSION >= 201402L
+            std::less<>
+        #else
+            std::less<std::string>
+        #endif
+        comparator_t;
+    }
+
     /** Concrete variables map which store variables in real map.
 
         This class is derived from std::map<std::string, variable_value>,
         so you can use all map operators to examine its content.
     */
     class BOOST_PROGRAM_OPTIONS_DECL variables_map : public abstract_variables_map,
-                               public std::map<std::string, variable_value>
+                               public std::map<std::string, variable_value, details::comparator_t>
     {
     public:
         variables_map();
diff --git a/src/variables_map.cpp b/src/variables_map.cpp
index 94ac6148c..97d322672 100644
--- a/src/variables_map.cpp
+++ b/src/variables_map.cpp
@@ -32,7 +32,7 @@ namespace boost { namespace program_options {
 
         // We need to access map's operator[], not the overriden version
         // variables_map. Ehmm.. messy.
-        std::map<std::string, variable_value>& m = xm;
+        std::map<std::string, variable_value, details::comparator_t>& m = xm;
 
         std::set<std::string> new_final;
 
@@ -194,7 +194,7 @@ namespace boost { namespace program_options {
 
     void variables_map::clear()
     {
-        std::map<std::string, variable_value>::clear();
+        std::map<std::string, variable_value, details::comparator_t>::clear();
         m_final.clear();
         m_required.clear();
     }
@@ -220,7 +220,7 @@ namespace boost { namespace program_options {
         {
             const string& opt = r->first;
             const string& display_opt = r->second;
-            map<string, variable_value>::const_iterator iter = find(opt);
+            map<string, variable_value, details::comparator_t>::const_iterator iter = find(opt);
             if (iter == end() || iter->second.empty())
             {
                 boost::throw_exception(required_option(display_opt));
@@ -229,7 +229,7 @@ namespace boost { namespace program_options {
         }
 
         // Lastly, run notify actions.
-        for (map<string, variable_value>::iterator k = begin();
+        for (map<string, variable_value, details::comparator_t>::iterator k = begin();
              k != end();
              ++k)
         {
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ea8832ec1..70f9b0242 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -23,5 +23,6 @@ boost_test(TYPE run SOURCES unrecognized_test.cpp)
 boost_test(TYPE run SOURCES required_test.cpp ARGUMENTS ${CMAKE_CURRENT_SOURCE_DIR}/required_test.cfg)
 boost_test(TYPE run SOURCES exception_txt_test.cpp)
 boost_test(TYPE run SOURCES optional_test.cpp)
+boost_test(TYPE run SOURCES transparent_comparator_test.cpp)
 
 boost_test(TYPE run SOURCES quick.cpp ARGUMENTS --path=initial LINK_LIBRARIES Boost::core)
diff --git a/test/transparent_comparator_test.cpp b/test/transparent_comparator_test.cpp
new file mode 100644
index 000000000..b51bd97c2
--- /dev/null
+++ b/test/transparent_comparator_test.cpp
@@ -0,0 +1,56 @@
+#include <boost/config.hpp>
+#include <boost/core/noncopyable.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility/string_view.hpp>
+
+#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
+#include <string_view>
+#endif
+
+namespace {
+// Contrived class that proves no extra copies are being made and only operator< is being used
+struct Dummy : private boost::noncopyable
+{};
+
+bool operator<(const Dummy&, const std::string& rhs) { return "test" < rhs; }
+bool operator<(const std::string& lhs, const Dummy&) { return lhs < "test"; }
+}
+
+void test_transparent_comparator()
+{
+    boost::program_options::variables_map vm;
+    vm.insert({"test", boost::program_options::variable_value(42, false)});
+
+    boost::program_options::variables_map::iterator iter;
+
+    // c-string literal.
+    // If pre c++14, a std::string object will be implicitly created on the call to find()
+    // after c++14 no extra object will be created
+    iter = vm.find("test");
+    BOOST_REQUIRE(iter != vm.end());
+    BOOST_CHECK(boost::any_cast<int>(iter->second.value()) == 42);
+
+    // Rest of the checks require c++14 for a transparent comparator
+#ifdef BOOST_CXX_VERSION > 201402L
+    // boost::string_view
+    const boost::string_view bsv("test");
+    iter = vm.find(bsv);
+    BOOST_REQUIRE(iter != vm.end());
+    BOOST_CHECK(boost::any_cast<int>(iter->second.value()) == 42);
+
+    #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
+    // std::string_view
+    const std::string_view sv("test");
+    iter = vm.find(sv);
+    BOOST_REQUIRE(iter != vm.end());
+    BOOST_CHECK(boost::any_cast<int>(iter->second.value()) == 42);
+    #endif
+
+    // custom class
+    Dummy d;
+    iter = vm.find(d);
+    BOOST_REQUIRE(iter != vm.end());
+    BOOST_CHECK(boost::any_cast<int>(iter->second.value()) == 42);
+#endif
+}