diff --git a/include/pybind11/common.h b/include/pybind11/common.h
index 62198c341..e684b187e 100644
--- a/include/pybind11/common.h
+++ b/include/pybind11/common.h
@@ -16,6 +16,18 @@
 #  define NAMESPACE_END(name) }
 #endif
 
+// Neither MSVC nor Intel support enough of C++14 yet (in particular, as of MSVC 2015 and ICC 17
+// beta, neither support extended constexpr, which we rely on in descr.h), so don't enable pybind
+// CPP14 features for them.
+#if !defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+#  if __cplusplus >= 201402L
+#    define PYBIND11_CPP14
+#    if __cplusplus > 201402L /* Temporary: should be updated to >= the final C++17 value once known */
+#      define PYBIND11_CPP17
+#    endif
+#  endif
+#endif
+
 #if !defined(PYBIND11_EXPORT)
 #  if defined(WIN32) || defined(_WIN32)
 #    define PYBIND11_EXPORT __declspec(dllexport)
@@ -30,7 +42,7 @@
 #  define PYBIND11_NOINLINE __attribute__ ((noinline))
 #endif
 
-#if __cplusplus > 201103L
+#if defined(PYBIND11_CPP14)
 #  define PYBIND11_DEPRECATED(reason) [[deprecated(reason)]]
 #elif defined(__clang__)
 #  define PYBIND11_DEPRECATED(reason) __attribute__((deprecated(reason)))
diff --git a/include/pybind11/descr.h b/include/pybind11/descr.h
index f8a349b1a..a9a1f67aa 100644
--- a/include/pybind11/descr.h
+++ b/include/pybind11/descr.h
@@ -15,18 +15,6 @@
 NAMESPACE_BEGIN(pybind11)
 NAMESPACE_BEGIN(detail)
 
-#if defined(__INTEL_COMPILER)
-/* C++14 features not supported for now */
-#elif defined(__clang__)
-#  if __has_feature(cxx_return_type_deduction) && __has_feature(cxx_relaxed_constexpr)
-#    define PYBIND11_CPP14
-#  endif
-#elif defined(__GNUG__)
-#  if __cpp_constexpr >= 201304 && __cpp_decltype_auto >= 201304
-#    define PYBIND11_CPP14
-#  endif
-#endif
-
 #if defined(PYBIND11_CPP14) /* Concatenate type signatures at compile time using C++14 */
 
 template <size_t Size1, size_t Size2> class descr {
diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h
index 4da67df2b..ae0b3affb 100644
--- a/include/pybind11/stl.h
+++ b/include/pybind11/stl.h
@@ -22,14 +22,14 @@
 #pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
 #endif
 
-#if defined(PYBIND11_CPP14) && defined(__has_include)
-// std::optional
-#  if __has_include(<optional>)
+#ifdef __has_include
+// std::optional (but including it in c++14 mode isn't allowed)
+#  if defined(PYBIND11_CPP17) && __has_include(<optional>)
 #    include <optional>
 #    define PYBIND11_HAS_OPTIONAL 1
 #  endif
-// std::experimental::optional
-#  if __has_include(<experimental/optional>)
+// std::experimental::optional (but not allowed in c++11 mode)
+#  if defined(PYBIND11_CPP14) && __has_include(<experimental/optional>)
 #    include <experimental/optional>
 #    if __cpp_lib_experimental_optional  // just in case
 #      define PYBIND11_HAS_EXP_OPTIONAL 1