Skip to content

Commit

Permalink
Consistently use "int = 0" SFINAE (#226)
Browse files Browse the repository at this point in the history
Fixes #187.

Add TRANSITION comments for #248 and #249, blocked by compiler bugs.

Add `_Enabled` names. When we don't have `enable_if_t`, this makes the
template parameter's purpose clearer. When we do have `enable_if_t`
but without `= 0`, this makes it somewhat clearer that we haven't
forgotten the default argument (it's simply elsewhere).
  • Loading branch information
miscco authored and StephanTLavavej committed Nov 2, 2019
1 parent 28ec9a3 commit 3b0a1c9
Show file tree
Hide file tree
Showing 22 changed files with 128 additions and 119 deletions.
2 changes: 1 addition & 1 deletion stl/inc/array
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ public:
_Ty _Elems[1];
};

template <class _Ty, size_t _Size, class = enable_if_t<_Size == 0 || _Is_swappable<_Ty>::value>>
template <class _Ty, size_t _Size, enable_if_t<_Size == 0 || _Is_swappable<_Ty>::value, int> = 0>
void swap(array<_Ty, _Size>& _Left, array<_Ty, _Size>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
return _Left.swap(_Right);
}
Expand Down
36 changes: 19 additions & 17 deletions stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace chrono {
template <class _Ty>
_INLINE_VAR constexpr bool _Is_duration_v = _Is_specialization_v<_Ty, duration>;

template <class _To, class _Rep, class _Period, class = enable_if_t<_Is_duration_v<_To>>>
template <class _To, class _Rep, class _Period, enable_if_t<_Is_duration_v<_To>, int> = 0>
constexpr _To duration_cast(const duration<_Rep, _Period>&) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<typename _To::rep>); // strengthened

Expand All @@ -75,16 +75,18 @@ namespace chrono {
constexpr duration() = default;

template <class _Rep2,
class = enable_if_t<is_convertible_v<const _Rep2&,
_Rep> && (treat_as_floating_point_v<_Rep> || !treat_as_floating_point_v<_Rep2>)>>
enable_if_t<is_convertible_v<const _Rep2&,
_Rep> && (treat_as_floating_point_v<_Rep> || !treat_as_floating_point_v<_Rep2>),
int> = 0>
constexpr explicit duration(const _Rep2& _Val) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<_Rep2>) // strengthened
: _MyRep(static_cast<_Rep>(_Val)) {}

template <class _Rep2, class _Period2,
class = enable_if_t<
enable_if_t<
treat_as_floating_point_v<
_Rep> || (_Ratio_divide_sfinae<_Period2, _Period>::den == 1 && !treat_as_floating_point_v<_Rep2>)>>
_Rep> || (_Ratio_divide_sfinae<_Period2, _Period>::den == 1 && !treat_as_floating_point_v<_Rep2>),
int> = 0>
constexpr duration(const duration<_Rep2, _Period2>& _Dur) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<_Rep2>) // strengthened
: _MyRep(chrono::duration_cast<duration>(_Dur).count()) {}
Expand Down Expand Up @@ -185,7 +187,7 @@ namespace chrono {
constexpr explicit time_point(const _Duration& _Other) noexcept(is_arithmetic_v<rep>) // strengthened
: _MyDur(_Other) {}

template <class _Duration2, class = enable_if_t<is_convertible_v<_Duration2, _Duration>>>
template <class _Duration2, enable_if_t<is_convertible_v<_Duration2, _Duration>, int> = 0>
constexpr time_point(const time_point<_Clock, _Duration2>& _Tp) noexcept(
is_arithmetic_v<rep>&& is_arithmetic_v<typename _Duration2::rep>) // strengthened
: _MyDur(_Tp.time_since_epoch()) {}
Expand Down Expand Up @@ -256,7 +258,7 @@ namespace chrono {
}

template <class _Rep1, class _Period1, class _Rep2,
class = enable_if_t<is_convertible_v<const _Rep2&, common_type_t<_Rep1, _Rep2>>>>
enable_if_t<is_convertible_v<const _Rep2&, common_type_t<_Rep1, _Rep2>>, int> = 0>
_NODISCARD constexpr duration<common_type_t<_Rep1, _Rep2>, _Period1> operator*(
const duration<_Rep1, _Period1>& _Left,
const _Rep2& _Right) noexcept(is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ {
Expand All @@ -266,7 +268,7 @@ namespace chrono {
}

template <class _Rep1, class _Rep2, class _Period2,
class = enable_if_t<is_convertible_v<const _Rep1&, common_type_t<_Rep1, _Rep2>>>>
enable_if_t<is_convertible_v<const _Rep1&, common_type_t<_Rep1, _Rep2>>, int> = 0>
_NODISCARD constexpr duration<common_type_t<_Rep1, _Rep2>, _Period2>
operator*(const _Rep1& _Left, const duration<_Rep2, _Period2>& _Right) noexcept(
is_arithmetic_v<_Rep1>&& is_arithmetic_v<_Rep2>) /* strengthened */ {
Expand Down Expand Up @@ -372,7 +374,7 @@ namespace chrono {
}

// FUNCTION TEMPLATE duration_cast
template <class _To, class _Rep, class _Period, class _Enabled>
template <class _To, class _Rep, class _Period, enable_if_t<_Is_duration_v<_To>, int> _Enabled>
_NODISCARD constexpr _To duration_cast(const duration<_Rep, _Period>& _Dur) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// convert duration to another duration; truncate
Expand Down Expand Up @@ -403,7 +405,7 @@ namespace chrono {
}

// FUNCTION TEMPLATE floor
template <class _To, class _Rep, class _Period, class = enable_if_t<_Is_duration_v<_To>>>
template <class _To, class _Rep, class _Period, enable_if_t<_Is_duration_v<_To>, int> = 0>
_NODISCARD constexpr _To floor(const duration<_Rep, _Period>& _Dur) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// convert duration to another duration; round towards negative infinity
Expand All @@ -417,7 +419,7 @@ namespace chrono {
}

// FUNCTION TEMPLATE ceil
template <class _To, class _Rep, class _Period, class = enable_if_t<_Is_duration_v<_To>>>
template <class _To, class _Rep, class _Period, enable_if_t<_Is_duration_v<_To>, int> = 0>
_NODISCARD constexpr _To ceil(const duration<_Rep, _Period>& _Dur) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// convert duration to another duration; round towards positive infinity
Expand All @@ -438,7 +440,7 @@ namespace chrono {
}

template <class _To, class _Rep, class _Period,
class = enable_if_t<_Is_duration_v<_To> && !treat_as_floating_point_v<typename _To::rep>>>
enable_if_t<_Is_duration_v<_To> && !treat_as_floating_point_v<typename _To::rep>, int> = 0>
_NODISCARD constexpr _To round(const duration<_Rep, _Period>& _Dur) noexcept(
is_arithmetic_v<_Rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// convert duration to another duration, round to nearest, ties to even
Expand All @@ -455,7 +457,7 @@ namespace chrono {
}

// FUNCTION TEMPLATE abs
template <class _Rep, class _Period, class = enable_if_t<numeric_limits<_Rep>::is_signed>>
template <class _Rep, class _Period, enable_if_t<numeric_limits<_Rep>::is_signed, int> = 0>
_NODISCARD constexpr duration<_Rep, _Period> abs(const duration<_Rep, _Period> _Dur) noexcept(
is_arithmetic_v<_Rep>) /* strengthened */ {
// create a duration with count() the absolute value of _Dur.count()
Expand Down Expand Up @@ -545,23 +547,23 @@ namespace chrono {
}

// FUNCTION TEMPLATE time_point_cast
template <class _To, class _Clock, class _Duration, class = enable_if_t<_Is_duration_v<_To>>>
template <class _To, class _Clock, class _Duration, enable_if_t<_Is_duration_v<_To>, int> = 0>
_NODISCARD constexpr time_point<_Clock, _To> time_point_cast(const time_point<_Clock, _Duration>& _Time) noexcept(
is_arithmetic_v<typename _Duration::rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// change the duration type of a time_point; truncate
return time_point<_Clock, _To>(chrono::duration_cast<_To>(_Time.time_since_epoch()));
}

// FUNCTION TEMPLATE floor (for time_point instances)
template <class _To, class _Clock, class _Duration, class = enable_if_t<_Is_duration_v<_To>>>
template <class _To, class _Clock, class _Duration, enable_if_t<_Is_duration_v<_To>, int> = 0>
_NODISCARD constexpr time_point<_Clock, _To> floor(const time_point<_Clock, _Duration>& _Time) noexcept(
is_arithmetic_v<typename _Duration::rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// change the duration type of a time_point; round towards negative infinity
return time_point<_Clock, _To>(chrono::floor<_To>(_Time.time_since_epoch()));
}

// FUNCTION TEMPLATE ceil (for time_point instances)
template <class _To, class _Clock, class _Duration, class = enable_if_t<_Is_duration_v<_To>>>
template <class _To, class _Clock, class _Duration, enable_if_t<_Is_duration_v<_To>, int> = 0>
_NODISCARD constexpr time_point<_Clock, _To> ceil(const time_point<_Clock, _Duration>& _Time) noexcept(
is_arithmetic_v<typename _Duration::rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// change the duration type of a time_point; round towards positive infinity
Expand All @@ -570,7 +572,7 @@ namespace chrono {

// FUNCTION TEMPLATE round (for time_point instances)
template <class _To, class _Clock, class _Duration,
class = enable_if_t<_Is_duration_v<_To> && !treat_as_floating_point_v<typename _To::rep>>>
enable_if_t<_Is_duration_v<_To> && !treat_as_floating_point_v<typename _To::rep>, int> = 0>
_NODISCARD constexpr time_point<_Clock, _To> round(const time_point<_Clock, _Duration>& _Time) noexcept(
is_arithmetic_v<typename _Duration::rep>&& is_arithmetic_v<typename _To::rep>) /* strengthened */ {
// change the duration type of a time_point; round to nearest, ties to even
Expand Down
6 changes: 3 additions & 3 deletions stl/inc/complex
Original file line number Diff line number Diff line change
Expand Up @@ -1774,13 +1774,13 @@ struct _Promote_to_float { // promote integral to double
};

#define _GENERIC_MATHC0X(FUN, VAL) \
template <class _Ty, class = enable_if_t<is_arithmetic_v<_Ty>>> \
template <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, int> = 0> \
_NODISCARD typename _Promote_to_float<_Ty>::type FUN(_Ty) { \
return static_cast<typename _Promote_to_float<_Ty>::type>(VAL); \
}

#define _GENERIC_MATHC1X(FUN, VAL) \
template <class _Ty, class = enable_if_t<is_arithmetic_v<_Ty>>> \
template <class _Ty, enable_if_t<is_arithmetic_v<_Ty>, int> = 0> \
_NODISCARD typename _Promote_to_float<_Ty>::type FUN(_Ty _Left) { \
return static_cast<typename _Promote_to_float<_Ty>::type>(VAL); \
}
Expand Down Expand Up @@ -1816,7 +1816,7 @@ _NODISCARD complex<_Common_float_type_t<_Ty1, _Ty2>> pow(const _Ty1& _Left, cons
return _STD pow(type(_Left), type(_Right));
}

template <class _Ty1, class _Ty2, class = enable_if_t<is_integral_v<_Ty1> && is_integral_v<_Ty2>>>
template <class _Ty1, class _Ty2, enable_if_t<is_integral_v<_Ty1> && is_integral_v<_Ty2>, int> = 0>
_NODISCARD complex<_Ty1> pow(const complex<_Ty1>& _Left, _Ty2& _Right) {
// raise Gaussian integer to an integer power
using type = complex<_Ty1>;
Expand Down
8 changes: 4 additions & 4 deletions stl/inc/deque
Original file line number Diff line number Diff line change
Expand Up @@ -638,15 +638,15 @@ public:
_Proxy._Release();
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
deque(_Iter _First, _Iter _Last) : _Mypair(_Zero_then_variadic_args_t()) {
_Alproxy_ty _Alproxy(_Getal());
_Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
_Construct(_First, _Last);
_Proxy._Release();
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
deque(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t(), _Al) {
_Alproxy_ty _Alproxy(_Getal());
_Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data());
Expand Down Expand Up @@ -1147,7 +1147,7 @@ public:
#endif // _ITERATOR_DEBUG_LEVEL == 2
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
void assign(_Iter _First, _Iter _Last) {
_Orphan_all();
_Adl_verify_range(_First, _Last);
Expand Down Expand Up @@ -1214,7 +1214,7 @@ public:
return begin() + static_cast<difference_type>(_Off);
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) {
// insert [_First, _Last) at _Where, input iterators
size_type _Off = static_cast<size_type>(_Where - begin());
Expand Down
12 changes: 6 additions & 6 deletions stl/inc/experimental/filesystem
Original file line number Diff line number Diff line change
Expand Up @@ -749,15 +749,15 @@ public:

// ARBITRARY SOURCE CONSTRUCT

template <class _InIt, class = enable_if_t<_Is_iterator_v<_InIt>>>
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
path(_InIt _First, _InIt _Last) {
using _Valty = _Iter_value_t<_InIt>;
basic_string<_Valty> _Str(_First, _Last);
string_type _Str_out;
*this /= _Path_cvt<_Valty, value_type>::_Cvt(_Str_out, _Str.c_str(), _Str.size());
}

template <class _InIt, class = enable_if_t<_Is_iterator_v<_InIt>>>
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
path(_InIt _First) {
using _Valty = _Iter_value_t<_InIt>;
basic_string<_Valty> _Str;
Expand All @@ -777,15 +777,15 @@ public:

// ARBITRARY SOURCE CONSTRUCT, WITH LOCALE

template <class _InIt, class = enable_if_t<_Is_iterator_v<_InIt>>>
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
path(_InIt _First, _InIt _Last, const locale& _Loc) {
using _Valty = _Iter_value_t<_InIt>;
basic_string<_Valty> _Str(_First, _Last);
string_type _Str_out;
*this /= _Path_cvt<_Valty, value_type>::_Cvt(_Str_out, _Str.c_str(), _Str.size(), _Loc);
}

template <class _InIt, class = enable_if_t<_Is_iterator_v<_InIt>>>
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
path(_InIt _First, const locale& _Loc) {
using _Valty = _Iter_value_t<_InIt>;
basic_string<_Valty> _Str;
Expand Down Expand Up @@ -1305,14 +1305,14 @@ basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr,
}

// FUNCTION TEMPLATE u8path
template <class _InIt, class = enable_if_t<_Is_iterator_v<_InIt>>>
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
_NODISCARD path u8path(_InIt _First, _InIt _Last) { // make path from [_First, _Last) UTF8, given iterators
string _Str(_First, _Last);
path::string_type _Str_out;
return path(_Path_cvt<_Char8_t, _Pchar>::_Cvt(_Str_out, _Str.c_str(), _Str.size()));
}

template <class _InIt, class = enable_if_t<_Is_iterator_v<_InIt>>>
template <class _InIt, enable_if_t<_Is_iterator_v<_InIt>, int> = 0>
_NODISCARD path u8path(_InIt _First) { // make path from NTBS UTF8, given iterator
string _Str;
for (; *_First != '\0'; ++_First) {
Expand Down
8 changes: 4 additions & 4 deletions stl/inc/forward_list
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ public:
_Insert_op._Attach_after(_Mypair._Myval2._Before_head());
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
forward_list(_Iter _First, _Iter _Last) : _Mypair(_Zero_then_variadic_args_t()) {
_Adl_verify_range(_First, _Last);
_Flist_insert_after_op<_Alnode> _Insert_op(_Getal());
Expand All @@ -569,7 +569,7 @@ public:
_Insert_op._Attach_after(_Mypair._Myval2._Before_head());
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
forward_list(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t(), _Al) {
_Adl_verify_range(_First, _Last);
_Flist_insert_after_op<_Alnode> _Insert_op(_Getal());
Expand Down Expand Up @@ -908,7 +908,7 @@ private:
}

public:
template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
void assign(_Iter _First, _Iter _Last) {
_Adl_verify_range(_First, _Last);
_Assign_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last));
Expand Down Expand Up @@ -944,7 +944,7 @@ public:
return _Make_iter(_Where._Ptr);
}

template <class _Iter, class = enable_if_t<_Is_iterator_v<_Iter>>>
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
iterator insert_after(const_iterator _Where, _Iter _First, _Iter _Last) {
// insert [_First, _Last) after _Where
#if _ITERATOR_DEBUG_LEVEL == 2
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ public:
using _Mybase = _Func_base<_Rx, _Types...>;
using _Nothrow_move = is_nothrow_move_constructible<_Callable>;

template <class _Other, class = enable_if_t<!is_same_v<_Func_impl_no_alloc, decay_t<_Other>>>>
template <class _Other, enable_if_t<!is_same_v<_Func_impl_no_alloc, decay_t<_Other>>, int> = 0>
explicit _Func_impl_no_alloc(_Other&& _Val) : _Callee(_STD forward<_Other>(_Val)) {}

// dtor non-virtual due to _Delete_this()
Expand Down
4 changes: 2 additions & 2 deletions stl/inc/future
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,7 @@ public:

packaged_task() noexcept : _MyPromise(0) {}

template <class _Fty2, class = enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>>>
template <class _Fty2, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
explicit packaged_task(_Fty2&& _Fnarg) : _MyPromise(new _MyStateType(_STD forward<_Fty2>(_Fnarg))) {}

packaged_task(packaged_task&& _Other) noexcept : _MyPromise(_STD move(_Other._MyPromise)) {}
Expand All @@ -1363,7 +1363,7 @@ public:
}

#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
template <class _Fty2, class _Alloc, class = enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>>>
template <class _Fty2, class _Alloc, enable_if_t<!is_same_v<_Remove_cvref_t<_Fty2>, packaged_task>, int> = 0>
packaged_task(allocator_arg_t, const _Alloc& _Al, _Fty2&& _Fnarg)
: _MyPromise(_Make_packaged_state<_MyStateType>(_STD forward<_Fty2>(_Fnarg), _Al)) {}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
Expand Down
8 changes: 4 additions & 4 deletions stl/inc/hash_map
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,12 @@ namespace stdext {

using _Mybase::insert;

template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>>
template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>> // TRANSITION, GH-249
pair<iterator, bool> insert(_Valty&& _Val) {
return this->emplace(_STD forward<_Valty>(_Val));
}

template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>>
template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>> // TRANSITION, GH-249
iterator insert(const_iterator _Where, _Valty&& _Val) {
return this->emplace_hint(_Where, _STD forward<_Valty>(_Val));
}
Expand Down Expand Up @@ -373,12 +373,12 @@ namespace stdext {

using _Mybase::insert;

template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>>
template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>> // TRANSITION, GH-249
iterator insert(_Valty&& _Val) {
return this->emplace(_STD forward<_Valty>(_Val));
}

template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>>
template <class _Valty, class = enable_if_t<is_constructible_v<value_type, _Valty>>> // TRANSITION, GH-249
iterator insert(const_iterator _Where, _Valty&& _Val) {
return this->emplace_hint(_Where, _STD forward<_Valty>(_Val));
}
Expand Down
Loading

0 comments on commit 3b0a1c9

Please sign in to comment.