我目前正在尝试编写一些灵活的编译时数学库,并刚刚遇到替代失败,我无法摆脱。这是问题:替换失败
首先,我正在写一个理性的类,我会把唯一需要的部分。
template<typename T>
class rational
{
static_assert(std::is_integral<T>::value, "Can only contain integral values.");
public:
constexpr rational(T numerator, T denominator);
private:
T _numerator;
T _denominator;
};
,并允许该库是灵活的,我试图让一个大量使用SFINAE,以限制操作的函数调用唯一合理的,理性的,理性的积分和积分理性的,但是这将无论积分是什么和基本类型如何。下面是operator+
比如函数声明:
template<typename T, typename U>
constexpr
rational<typename std::common_type<T, U>::type>
operator+(const rational<T>& lhs, const rational<U>& rhs);
template<typename T, typename U>
constexpr
typename std::enable_if<std::is_integral<U>::value, rational<typename std::common_type<T, U>::type>>::type
operator+(const rational<T>& lhs, const U& rhs);
template<typename T, typename U>
constexpr
typename std::enable_if<std::is_integral<T>::value, rational<typename std::common_type<T, U>::type>>::type
operator+(const T& lhs, const rational<U> rhs);
这里是代码故障段。它不会因为static_assert
但替代大概是因为失败的崩溃:
constexpr auto r1 = rational<int>(1, 2);
constexpr auto r2 = rational<int>(2, 4);
static_assert(r1 + r2 == rational<int>(1, 1), "");
的错误是下面(我只保留而不被周围布拉布拉错误):
... required by substitution of 'template<class T, class U> constexpr typename std::enable_if<std::is_integral<T>::value, smath::rational<typename std::common_type<_Tp, _Up>::type> >::type smath::operator+(const T&, smath::rational<U>) [with T = smath::rational<int>; U = int]'
... required from here
... error: operands to ?: have different types 'smath::rational<int>' and 'int'
... required by substitution of 'template<class T, class U> constexpr typename std::enable_if<std::is_integral<U>::value, smath::rational<typename std::common_type<_Tp, _Up>::type> >::type smath::operator+(const smath::rational<T>&, const U&) [with T = int; U = smath::rational<int>]'
... required from here
... error: operands to ?: have different types 'int' and 'smath::rational<int>'
我的猜测是, g ++会选择与两个有理数一起工作的第一个模板函数,并且可以。但是,它似乎仍然尝试应用最后两个函数,并在尝试这样做时失败。我无法理解。一些帮助将受到欢迎:)
编辑:似乎具有rational
构造explicit
解决问题,这是伟大的。不过,我仍然很想知道替代失败的原因。
也许你试图添加一个int到基于模板的变量,它不能解决冲突?你有一个operator +,它的一边是smath :: rational,另一边是int?相反呢?由于您使用的是重载的“+”运算符,因此请将每个“a + b”的情况视为对所述运算符的调用,并相应地验证类型。 – Ghost2
我的'operator +'函数采用两个有理数或一个有理数的整数值(无论哪种整数类型)。有一个用于右侧的整数值,另一个用于左侧的整数值。当我给出一个有理数和一个整数值时,这些断言很有效。它只是失败了两个有理数。 – Morwenn