Override output operator << inside class C++ to print std::vector

huangapple go评论71阅读模式
英文:

Override output operator << inside class c++ to print std::vector

问题

下面是您提供的代码的翻译:

让我们假设我有以下类:
#include <iostream>
#include <cmath>
#include <vector>
#include <complex>

class RootFinder {
public:
    RootFinder() = default;
    ~RootFinder() = default;

    friend std::ostream& operator<<(std::ostream& os, const std::vector<std::complex<double>>& v) 
    { 
        os << "[";
        for (int i = 0; i < v.size(); ++i) { 
            os << "(" << v[i].real() << "," << v[i].imag() << "), "; 
        }
        os << "]\n";
        return os; 
    }

    inline std::vector<std::complex<double>> calculateEigenValuesOfMatrix(){
        std::vector<std::complex<double>> eigen_values;
        //  执行一些操作
        std::cout << eigen_values << std::endl;
        return eigen_values;
    };
    
private:
    
};

int main (){
    RootFinder root_finder;
    root_finder.calculateEigenValuesOfMatrix();
    return 0;
}

问题:
我想在类内部打印 eigen_values

我试图重载 std::ostream&,但并没有解决问题。如何正确解决这个问题?

错误:

错误:没有与 'operator<<' 匹配的操作数类型(操作数类型为 'std::ostream {aka std::basic_ostream<char>}'  'std::vector<std::complex<double>>')
             std::cout << eigen_values << std::endl;
             ~~~~~~~~~^~~~~~~~~~~~~~~
在文件包含自/usr/include/c++/7/istream:39:0,
                 from /usr/include/c++/7/sstream:38,
                 from /usr/include/c++/7/complex:45,
                 from /usr/include/eigen3/Eigen/Core:80,
                 from /root/tmp/cmake_tittorials/include/root_finder.h:4,
                 from /root/tmp/cmake_tittorials/src/main.cpp:1:

如果您有任何其他问题或需要进一步的帮助,请随时提问。

英文:

Let's say I have a class as follows:

#include &lt;iostream&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;
#include &lt;complex&gt;

class RootFinder {
    public:
        RootFinder() = default;
        ~RootFinder() = default;

        friend std::ostream&amp;  operator&lt;&lt;(std::ostream&amp; os, const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v) 
        { 
            os &lt;&lt; &quot;[&quot;;
            for (int i = 0; i &lt; v.size(); ++i) { 
                os &lt;&lt;&quot;( &quot;&lt;&lt; v[i].real() &lt;&lt; &quot;,&quot; &lt;&lt; v[i].imag() &lt;&lt; &quot;), &quot;; 
            }
            os &lt;&lt; &quot;]\n&quot;;
            return os; 
        }

        inline std::vector&lt;std::complex&lt;double&gt;&gt; calculateEigenValuesOfMatrix(){
            std::vector&lt;std::complex&lt;double&gt;&gt; eigen_values;
            //  Do some operation
            std::cout&lt;&lt; eigen_values &lt;&lt; std::endl;
            return eigen_values;
        };
    
    private:
        
};

int main (){
    RootFinder root_finder;
    root_finder.calculateEigenValuesOfMatrix();
    return 0;
}

Question:
I want to print eigen_values inside the class itself.

I was trying to override the std::ostream&, but it does not solve the problem. What is the proper way to solve this?

Error:

error: no match for ‘operator&lt;&lt;’ (operand types are ‘std::ostream {aka std::basic_ostream&lt;char&gt;}’ and ‘std::vector&lt;std::complex&lt;double&gt; &gt;’)
             std::cout&lt;&lt; eigen_values &lt;&lt; std::endl;
             ~~~~~~~~~^~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/istream:39:0,
                 from /usr/include/c++/7/sstream:38,
                 from /usr/include/c++/7/complex:45,
                 from /usr/include/eigen3/Eigen/Core:80,
                 from /root/tmp/cmake_tittorials/include/root_finder.h:4,
                 from /root/tmp/cmake_tittorials/src/main.cpp:1:

答案1

得分: 4

以下是您要翻译的部分:

"The problem is that even though you have defined the overloaded friend operator<< inside the class, it is not visible through normal lookup until either it is also declared in the enclosing scope or it has a parameter of the class type(so that ADL finds the friend function declaration)."

"方法1"

"Here we provide a forward declaration for the friend function in the enclosing scope."

"Other option is to define the friend function outside the class as shown here"

英文:

The problem is that even though you have defined the overloaded friend operator&lt;&lt; inside the class, it is not visible through normal lookup until either it is also declared in the enclosing scope or it has a parameter of the class type(so that ADL finds the friend function declaration).

<h4>Method 1</h4>

Here we provide a forward declaration for the friend function in the enclosing scope.

#include &lt;iostream&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;
#include &lt;complex&gt;

//add this declaration in the enclosing scope
std::ostream&amp;  operator&lt;&lt;(std::ostream&amp; os, const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v);

class RootFinder {
    //exact same code as before
        
};
int main (){
    RootFinder root_finder;
    root_finder.calculateEigenValuesOfMatrix();
    return 0;
}

working demo


Other option is to define the friend function outside the class as shown here

答案2

得分: 0

如果您希望仅打印特征值,最好创建一个独立的函数(全局自由函数或本地私有函数)来打印这些值:

class RootFinder
{
private:
    void print_eigen_values(const std::vector<std::complex<double>>& v) const
    {
        // TODO: 添加用于打印到 std::cout 的逻辑
    }
};

如果您想要将特征值打印到任何 std::ostream,则可以创建以下函数:

class RootFinder
{
private:
    std::ostream& print_eigen_values(std::ostream& os, const std::vector<std::complex<double>>& v) const
    {
        // TODO: 添加用于打印到 os 的逻辑
        return os;
    }
};

然后可以这样使用它:print_eigen_values(std::cout, eigen_values) << std::endl;

如果您希望保留特征值以供将来操作,最好将它们作为 RootFinder 的成员,并可以像下面这样重载 std::ostream

class RootFinder
{
private:
    friend std::ostream& operator<<(std::ostream& os, const RootFinder& v)
    {
        // TODO: 添加用于将 v.m_eigen_values 打印到 os 的逻辑
        return os;
    }

    std::vector<std::complex<double>> m_eigen_values;
};

然后您可以在任何地方像这样使用它:

RootFinder r;
// ...
std::cout << r << std::endl;
英文:

If you wish to only print eigen values, better to create a standalone function (global free function or local private function) for printing the values:

class RootFinder
{
private:
    void print_eigen_values(const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v) const
    {
        // TODO: add logic for printing to std::cout
    }
};

If you wish to print eigen values to any std::ostream, then you can create a function like:

class RootFinder
{
private:
    std::ostream&amp; print_eigen_values(std::ostream&amp; os, const std::vector&lt;std::complex&lt;double&gt;&gt;&amp; v) const
    {
        // TODO: add logic for printing to os
        return os;
    }
};

then use it like: print_eigen_values(std::cout, eigen_values) &lt;&lt; std::endl;.

If you want to retain eigen values for future operations, better to keep them as member of RootFinder and then you can overload std::ostream like below:

class RootFinder
{
private:
    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const RootFinder&amp; v) const
    {
        // TODO: add logic for printing v.m_eigen_values to os
        return os;
    }

    std::vector&lt;std::complex&lt;double&gt;&gt; m_eigen_values;
};

which you can use anywhere like:

RootFinder r;
...
std::cout &lt;&lt; r &lt;&lt; std::endl;

huangapple
  • 本文由 发表于 2023年3月8日 15:59:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75670540.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定