Another esoteric libc++ issue: std::chrono::operator* SFINA

This device fails for 'std::chrono::operator*', but not for '/'. '*' triggers an error if 'typename common_type<_Rep1, _Rep2>::type' is not valid; '/' sinks that constraint into a dependent type, letting the template be removed by SFINAE instead. My recollection is that the standard calls for the '/' behavior.

    #include <chrono>
    namespace {
        struct any {
            template<class T> any(const T &);
        template<class A, class B>
        decltype(operator*(std::declval<A>(), std::declval<B>()),
        help_are_multiplicable(A, B);
        help_are_multiplicable(any, any);
        template<class A, class B>
        class are_multiplicable : public decltype(
            help_are_multiplicable(std::declval<A>(), std::declval<B>())
        ) { };
                  "fails"); // expect-error

This implementation may be useful as reference:

    template<typename D, typename R,
             bool Arith = carbonite::is_arithmetic<R>::value>
    struct dur_rep_mul_result_type_ : public enable_if2<false> { };
    template<typename DR, typename DP, typename R>
    struct dur_rep_mul_result_type_<duration<DR,DP>,R,true> : public enable_if2<
            R,typename carbonite::common_type<DR,R>::type
        duration<typename carbonite::common_type<DR,R>::type,DP>
    > { };
    template<typename R1, typename P, typename R2>
    typename dur_rep_mul_result_type_<duration<R1,P>,R2>::type
    operator*(const duration<R1,P> &d, const R2 &s);
    template<typename R1, typename P, typename R2>
    typename dur_rep_mul_result_type_<duration<R2,P>,R1>::type
    operator*(const R1 &s, const duration<R2,P> &d);

-- Gordon

chrono-mul-sfinae.cpp (1.05 KB)

Makefile (101 Bytes)