The proposal that added that N4387: Improving pair and tuple, revision 3 has an example of how it works:
Consider the following class template A that is intended to be used
as a wrapper for some other type T:#include <type_traits> #include <utility> template<class T> struct A { template<class U, typename std::enable_if< std::is_constructible<T, U>::value && std::is_convertible<U, T>::value , bool>::type = false > A(U&& u) : t(std::forward<U>(u)) {} template<class U, typename std::enable_if< std::is_constructible<T, U>::value && !std::is_convertible<U, T>::value , bool>::type = false > explicit A(U&& u) : t(std::forward<U>(u)) {} T t; };
The shown constructors both use perfect forwarding and they have
essentially the same signatures except for one being explicit, the
other one not. Furthermore, they are mutually exclusively constrained.
In other words: This combination behaves for any destination type T
and any argument type U like a single constructor that is either
explicit or non-explicit (or no constructor at all).
As Praetorian points out this is exactly how libstdc++ implements it.
If we modify the OPs example accordingly, it also works:
struct S {
template <typename T,
typename std::enable_if< std::is_integral<T>::value, bool>::type = false>
S(T) {}
template <typename T,
typename std::enable_if<!std::is_integral<T>::value, bool>::type = false>
explicit S(T) {}
};