在下面的代码中,我的意图是仅在模板参数Weighted<T>::operator+=
具有T
和operator+=
的情况下定义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;
}
};
我应该怎么做?如果问题出在编译器的版本上,是否有一个简单的解决方法来避免必须升级编译器?
答案 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)
{ /*..*/ }