SFINAE问题与特征检测分裂
我有以下特征来检测两种类型是否可分,并返回结果操作类型或其他Default
类型:
struct default_t { };
// Overloaded template for fallbacks
template <class U, class V>
default_t operator/(U, V);
// If the expression std::declval<U>()/std::declval<V>() is valid,
// gives the return type, otherwize provide Default.
template <class U, class V, class Default>
struct div_type_or {
using type_ = decltype(std::declval<U>() / std::declval<V>());
using type = typename std::conditional<
std::is_same<type_, default_t>{},
Default,
type_>::type;
};
template <class... Args>
using div_type_or_t = typename div_type_or<Args...>::type;
这适用于libstdc ++,但不适用于libc ++,当我尝试使用不可分的std::chrono::duration
类型时,例如:
struct A { };
div_type_or_t<std::chrono::seconds, A, int> b;
我收到以下错误:
/ Library / Developer / CommandLineTools / usr / include / c ++ / v1 / chrono:764:81:错误:没有类型在'std :: __ 1 :: common_type'中输入'type'typename common_type :: type> :: value>〜 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ ^ ~~~
/ Library / Developer / CommandLineTools / usr / include / c ++ / v1 / chrono:777:7:note:在实例化__duration_divide_imp的缺省参数时,需要A>'here:__duration_divide_imp,_Rep2> ^ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/ Library / Developer / CommandLineTools / usr / include / c ++ / v1 / chrono:784:10:note:在实例化模板类'std :: __ 1 :: chrono :: __ duration_divide_result>,A,false>'这里请求typename __duration_divide_result ,_Rep2> :: type ^
test.cpp:16:46:注意:在使用类型将推导模板参数代入函数模板'operator /'[使用_Rep1 = long long,_Period = std :: __ 1 :: ratio <1,1>,Rep2 = A] = decltype(std :: declval()/ std :: declval()); ^
test.cpp:24:1:note:在实例化模板类'div_type_or>时,A,D>'使用div_type_or_t = typename div_type_or :: type; ^
test.cpp:48:19:note:在实例化模板类型别名'div_type_or_t'时请求div_type_or_t,D> {},“”);
据我了解,这是因为operator/
对于std::chrono::duration
的以下重载失败:
template< class Rep1, class Period, class Rep2 >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
constexpr operator/( const duration<Rep1, Period>& d,
const Rep2& s );
我认为,因为std::common_type
是函数签名的一部分,这将允许SFINAE工作并使用我的operator/
自定义重载,从而推导出default_t
,但显然这不起作用...
既然这与libstdc ++一起工作,我只想知道我的代码是否有问题(也许我不明白SFINAE在这种情况下的工作方式),还是这是一个libc ++错误?
在libc ++中,我们有:
template <class _Duration, class _Rep, bool = __is_duration<_Rep>::value>
struct __duration_divide_result
{
};
template <class _Duration, class _Rep2,
bool = is_convertible<_Rep2,
typename common_type<typename _Duration::rep, _Rep2>::type>::value>
struct __duration_divide_imp
{
};
template <class _Rep1, class _Period, class _Rep2>
struct __duration_divide_imp<duration<_Rep1, _Period>, _Rep2, true>
{
typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period> type;
};
template <class _Rep1, class _Period, class _Rep2>
struct __duration_divide_result<duration<_Rep1, _Period>, _Rep2, false>
: __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>
{
};
template <class _Rep1, class _Period, class _Rep2>
inline _LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR
typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
{
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
typedef duration<_Cr, _Period> _Cd;
return _Cd(_Cd(__d).count() / static_cast<_Cr>(__s));
}
因此,而不是std::common_type<_Rep1, _Rep2>::type
,
他们使用__duration_divide_result<duration<_Rep1, _Period>, _Rep2 /*, false*/>
,
实例化__duration_divide_imp<duration<_Rep1, _Period>, _Rep2 /*, is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value*/>
这种用法是一个严重的错误。
我会说在libc ++中的实现在这方面是不正确的。
链接地址: http://www.djcxy.com/p/90833.html