代码之家  ›  专栏  ›  技术社区  ›  Rubin

模版扣款投诉模棱两可考生

  •  6
  • Rubin  · 技术社区  · 6 年前

    我打算实施 乘法运算符 我的“稀疏向量”和“向量”类。下面的简化代码演示显示了我的问题

    这个 矢量 上课 矢量化

    #pragma once
    
    template <typename T>
    class Vector 
    {
    public:
        Vector() {}
    
        template <typename Scalar>
        friend Vector operator*(const Scalar &a, const Vector &rhs)     // #1
        {
            return Vector();
        }
    };
    

    这个 稀疏向量 上课 小精灵

    #pragma once
    #include "Vector.hpp"
    
    template <typename T>
    class SpVec 
    {
    public:
        SpVec() {}
    
        template <typename U>
        inline friend double operator*(const SpVec &spv, const Vector<U> &v)   // #2
        {
            return 0.0;
        }
    };
    

    中的测试代码 主CPP :

    #include "Vector.hpp"
    #include "SpVec.hpp"
    
    
    #include <iostream>
    
    int main() 
    {
        Vector<double> v;
    
        SpVec<double> spv;
    
        std::cout << spv * v;
        return 0;
    }
    

    我用

    g++ main.cpp -o test
    

    这就产生了模棱两可的模板推断错误

    main.cpp: In function ‘int main()’:
    main.cpp:13:26: error: ambiguous overload for ‘operator*’ (operand types are ‘SpVec<double>’ and ‘Vector<double>’)
            std::cout << spv * v;
                        ~~~~^~~
    In file included from main.cpp:2:0:
    SpVec.hpp:12:26: note: candidate: double operator*(const SpVec<T>&, const Vector<U>&) [with U = double; T = double]
        inline friend double operator*(const SpVec &spv, const Vector<U> &v)   // #2
                            ^~~~~~~~
    In file included from main.cpp:1:0:
    Vector.hpp:10:19: note: candidate: Vector<T> operator*(const Scalar&, const Vector<T>&) [with Scalar = SpVec<double>; T = double]
        friend Vector operator*(const Scalar &a, const Vector &rhs)     // #1
    

    我期待 #2 方法定义更接近我的调用。

    请帮助我理解这个模棱两可的错误是如何产生的,以及如何解决这个问题。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Oliv    6 年前

    我想出了另一个主意,先前的类型信息 Scalar 可与 SFAINE feature c++11 标准库结构 std::enable_if

    代码:

    矢量化

    #pragma once
    
    #include <iostream>
    #include <type_traits>
    
    template <typename T>
    class Vector
    {
    public:
        Vector() {}
    
        template <typename Scalar>
        typename std::enable_if<std::is_arithmetic<Scalar>::value, Vector<T>>::type
        operator*(const Scalar &rhs) const// #1
        {
            std::cout << "Vector * Scalar called." << std::endl;
            return Vector();
        }
    
        template <typename Scalar>
        inline friend typename std::enable_if<std::is_arithmetic<Scalar>::value, Vector<T>>::type
        operator*(const Scalar &lhs, const Vector &rhs)
        {
            std::cout << "Scalar * Vector called." << std::endl;
            return Vector();
        }
    };
    

    SPVEC.HPP

    #pragma once
    #include "Vector.hpp"
    
    #include <iostream>
    
    template <typename T>
    class SpVec
    {
    public:
        SpVec() {}
    
        template <typename U>
        inline double operator*(const Vector<U> &rhs) const // #2 as member function
        {
            std::cout << "SpVec * Vector called" << std::endl;
            return 0.0;
        }
    
        template <typename U>
        inline friend double operator*(const Vector<U> &lhs, const SpVec &rhs)
        {
            std::cout << "Vector * SpVec called" << std::endl;
            return 0.0;
        }
    };
    

    主CPP

    #include "SpVec.hpp"
    #include "Vector.hpp"
    
    #include <iostream>
    
    int main()
    {
        Vector<double> v;
        SpVec<double> spv;
    
        double a = spv * v;
        a = v * spv;
    
        Vector<double> vt;
        vt = v * 2.0;
        vt = 2.0 * v;
    
        return 0;
    }
    

    C++ 11

    g++ -std=c++11 main.cpp -o test
    

    结果:

    SpVec * Vector called.
    Vector * SpVec called.
    Vector * Scalar called.
    Scalar * Vector called.
    
        2
  •  0
  •   Gaurav Sehgal    6 年前

    关于 operator* SpVec<double> Vector<double> . 可以决定

    operator*(const Scalar &a, const Vector &rhs) 具有 scalar 作为 spvec<双> rhs 作为 矢量<双精度> .

    它也可以决定

    operator*(const SpVec &spv, const Vector<U> &v) 用SPV作为 spvec<双> U 作为 double

    解决这个问题的方法之一是 Vector::operator* 非朋友功能。

    Vector operator*(const Scalar &a)     // #1
    {
        //The other argument here will be accessed using this pointer.
        return Vector();
    }
    

    你可以称之为

    int main() 
    {
       Vector<double> v;
       SpVec<double> spv;
       std::cout << spv * v; // will call #2
       v * spv;              //will call #1
       return 0;
    }