尾随返回类型中SFINAE的GCC错误

时间:2019-06-07 07:22:53

标签: c++ gcc compiler-errors c++14 sfinae

在下面的代码中,我的意图是仅在模板参数Weighted<T>::operator+=具有Toperator+=的情况下定义operator*=。它在MSVC14上正常运行,但是GCC(经6.3.0测试)失败,并在指示的位置显示错误“与'operator * ='不匹配”(当T没有operator*=时)

template<typename T>
struct Weighted {
    double weight;
    T value;

    // ...

    // weighted mean
    template<typename U=T>
    auto operator+=(const Weighted<U>& other) -> decltype(value += other.value, value*=1.0, *this) {
// ***COMPILE ERROR*** ---------------------------------------------------->    ~~~~~^~~~~

        value *= weight;
        value += other.weight*other.value;
        weight += other.weight;
        value /= weight;
        return *this;
    }

    // scale weight
    Weighted<T>& operator*=(double multiplier) {
        weight *= multiplier;
        return *this;
    }
};

我应该怎么做?如果问题出在编译器的版本上,是否有一个简单的解决方法来避免必须升级编译器?

2 个答案:

答案 0 :(得分:0)

index | value  | number
  0   |  a_fo  |  999
  1   |  b_fo  |  999

还在第一行添加了一个检查,以约束template<typename U=T, typename = std::enable_if_t<std::is_same<U,T>::value>> auto operator+=(const Weighted<U>& other) -> decltype(value += other.value, std::declval<U&>()*=1.0, *this) { // ... } U相同。

答案 1 :(得分:0)

我会这样做:

#include  <experimental/type_traits>

using std::experimental::is_detected;

template <typename T, typename U>
using plus_equal_t = decltype(std::declval<T&>() += std::declval<U>());

template <typename T, typename U>
using time_equal_t = decltype(std::declval<T&>() += std::declval<U>());

// Define traits
template <typename T, typename U>
using has_plus_equal = is_detected<plus_equal_t, T, U>;

template <typename T, typename U>
using has_time_equal = is_detected<time_equal_t, T, U>;



template<typename T>
struct Weighted {
    double weight;
    T value;

    // ...

    // weighted mean
    template<typename U=T,
             std::enable_if_t<has_plus_equal<U, U>::value
                              && has_time_equal<U, double>::value, int> = 0>
    Weighted& operator+=(const Weighted<T>& other) {
        value *= weight;
        value += other.weight*other.value;
        weight += other.weight;
        value /= weight;
        return *this;
    }
    // ...
};

在C ++ 2a中,将其简化为:

Weighted& operator+=(const Weighted<T>& other)
    requires(has_plus_equal<T, T>::value && has_time_equal<T, double>::value)
{ /*..*/ }