繁体   English   中英

非成员运算符重载的 SFINAE

[英]SFINAE for an non-member operator overload

我有一个非成员运算符重载,我需要对其应用 SFINAE 以使其正常工作。 我在实施过程中遇到了困难,在网上寻找参考资料时找不到与我需要的类似的东西,我知道我花了一天的大部分时间试图让它工作但无济于事,希望能得到一些帮助社区。 基本上对于第一个操作数重载我需要 SFINAE 类型 std::is_arithmetic 和第二个需要 SFINAE 类型

并键入 std::is_class。 或者,如果您对下面的代码有任何其他建议,我们将不胜感激。 预先感谢您的帮助。

template <typename T>
class Matrix3D
{
public:
    //////////////////////////////////////////////////////////////////////////
    // *** CONSTRUCTORS ***
    //////////////////////////////////////////////////////////////////////////

    /// Default Constructor
    //
    Matrix3D(void);

    /// External initialization Constructor
    //
    Matrix3D(const T& p_11, const T& p_12, const T& p_13,
             const T& p_21, const T& p_22, const T& p_23,
             const T& p_31, const T& p_32, const T& p_33);
    
    ....
    
            /// Vector division by matrix eqv to [M]^-1 * {V}
    /// \param p_vector p_matrix
    /// SFINAE enable_if type V std::is_arithmetic
    //
    template <typename U, typename V>
    friend Vector3D<decltype(std::declval<U>() / std::declval<V>())> operator/ (const Vector3D<U>& p_vector, const Matrix3D<V>& p_matrix);

    /// Vector division by matrix eqv to [M]^-1 * {V}
    /// \param p_vector p_matrix
    /// SFINAE enable_if type P && type Q std::is_class
    //
    template <typename P, typename Q>
    friend Vector3D<decltype(std::declval<P>() / std::declval<Q>())> operator/ (const Vector3D<P>& p_vector, const Matrix3D<Q>& p_matrix);
    
....    
private:
    //////////////////////////////////////////////////////////////////////////
    // *** PRIVATE METHODS ***
    //////////////////////////////////////////////////////////////////////////

    //////////////////////////////////////////////////////////////////////////
    // *** PRIVATE DATA MEMBERS ***
    //////////////////////////////////////////////////////////////////////////

    /// Matrix m_elements
    //
    std::array<std::array<T, 3>, 3> m_elem;
}


/// Vector division by matrix eqv to [M]^-1 * {V}
/// \param p_vector p_matrix
/// SFINAE enable_if type V std::is_arithmetic
//
template <typename U, typename V>
Vector3D<decltype(std::declval<U>() / std::declval<V>())> operator/ (const Vector3D<U>& p_vector, const Matrix3D<V>& p_matrix)
{
    Matrix3D<V> matrixinv = p_matrix.Inverse();

    return static_cast<Vector3D<decltype(std::declval<U>() / std::declval<V>())>> (matrixinv * p_vector);
}


/// Vector division by matrix eqv to [M]^-1 * {V}
/// \param p_vector p_matrix
/// SFINAE enable_if type P && type Q std::is_class
//
template <typename P, typename Q>
Vector3D<decltype(std::declval<P>() / std::declval<Q>())> operator/ (const Vector3D<P>& p_vector, const Matrix3D<Q>& p_matrix)
{
    Matrix3D<Q> matrixinv = p_matrix.Inverse();
    Matrix3D<double> dmatrixinv(matrixinv.m_elem[0][0].Get(), matrixinv.m_elem[1][0].Get(), matrixinv.m_elem[2][0].Get(),
                                matrixinv.m_elem[0][1].Get(), matrixinv.m_elem[1][1].Get(), matrixinv.m_elem[2][1].Get(),
                                matrixinv.m_elem[0][2].Get(), matrixinv.m_elem[1][2].Get(), matrixinv.m_elem[2][2].Get());
    Vector3D<double> dvector(p_vector.GetX().Get(), p_vector.GetY().Get(), p_vector.GetZ().Get());

    Vector3D<double> dres = dmatrixinv * dvector;
    decltype(std::declval<U>() / std::declval<V>()) elem[3];
    return Vector3D<decltype(std::declval<U>() / std::declval<V>())>(elem[0].Set(dres.GetX()), elem[1].Set(dres.GetY()), elem[2].Set(dres.GetZ()));
}

您可以添加std::enable_if_t<your_condition<U, V>::value, int> = 0作为模板参数:

/// Vector division by matrix eqv to [M]^-1 * {V}
/// \param p_vector p_matrix
/// SFINAE enable_if type V std::is_arithmetic
//
template <typename U,
          typename V,
          std::enable_if_t<std::is_arithmetic<V>::value, int>/* = 0*/>
friend Vector3D<decltype(std::declval<U>() / std::declval<V>())>
operator/ (const Vector3D<U>& p_vector, const Matrix3D<V>& p_matrix);

/// Vector division by matrix eqv to [M]^-1 * {V}
/// \param p_vector p_matrix
/// SFINAE enable_if type P && type Q std::is_class
//
template <typename P,
          typename Q,
          std::enable_if_t<std::is_class<P>::value && std::is_class<Q>::value, int> /* = 0*/>
friend Vector3D<decltype(std::declval<P>() / std::declval<Q>())>
operator/ (const Vector3D<P>& p_vector, const Matrix3D<Q>& p_matrix);

演示

或在 C++20 中,您可能会使用requires

template <typename U, typename V>
friend Vector3D<decltype(std::declval<U>() / std::declval<V>())>
operator/ (const Vector3D<U>& p_vector, const Matrix3D<V>& p_matrix)
requires(std::is_arithmetic<V>::value);

template <typename P, typename Q>
friend Vector3D<decltype(std::declval<P>() / std::declval<Q>())>
operator/ (const Vector3D<P>& p_vector, const Matrix3D<Q>& p_matrix)
requires(std::is_class<P>::value && std::is_class<Q>::value);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM