如何在C++中正确定义模板的流运算符

How to properly define stream operators for templates in C++

本文关键字:运算符 定义 C++      更新时间:2023-10-16

我已经定义了转换函数fromStringtoString来处理任何类型。它们使用流运算符(<<)(>>)。这是代码。

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <sstream>
#include <cctype>
using namespace std;
template <class Num1>
struct Foo
{
    Num1 X, Y;
};
template <class T>
string toString( T (a))//////
{
    stringstream ss;
    ss << a;
    return(ss.str());
}
template <class T>
T fromString(const string &str)
{
    stringstream ss(str);
    T result;
    ss>>result;
    return(result);
}
template <class T>
void proc_FromString(const string &str, T (&a))
{
    a = fromString<T>(str);
};
template <class Num>
istream &operator>>(istream &input,Foo<Num> &c)
{
    input>>c.X>>c.Y;
    return input;
};

template <class Num>
ostream &operator<<(ostream &output, Foo<Num> (&c))
{
    output<<"Foo("<<c.X<<","<<c.Y<<")";
    return output;
};
int main(int argNum, char *args[])
{
    Foo<int> fa;
    proc_FromString("1 2",fa);
    int a;
    cout<<toString(a)<<endl;
    cout<<toString(fa)<<endl;
    return(0);
}

它有效。但它不是很理想:

template <class T>
string toString( T (a))//////
{
    stringstream ss;
    ss << a;
    return(ss.str());
}

我在这里复制函数中的参数,而不是通过引用给出参数。

嗯。我建议这些改变会让它变得更好(在代码中重新定义):

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <sstream>
#include <cctype>
using namespace std;
template <class Num1>
struct Foo
{
    Num1 X, Y;
};
template <class T>
string toString(const T (&a))////// Redefining there!!!!
{
    stringstream ss;
    ss << a;
    return(ss.str());
}
template <class T>
T fromString(const string &str)
{
    stringstream ss(str);
    T result;
    ss>>result;
    return(result);
}
template <class T>
void proc_FromString(const string &str, T (&a))
{
    a = fromString<T>(str);
};
template <class Num>
istream &operator>>(istream &input,Foo<Num> &c)
{
    input>>c.X>>c.Y;
    return input;
};

template <class Num>
ostream &operator<<(ostream &output, Foo<Num> (&c))
{
    output<<"Foo("<<c.X<<","<<c.Y<<")";
    return output;
};
int main(int argNum, char *args[])
{
    Foo<int> fa;
    proc_FromString("1 2",fa);
    int a;
    cout<<toString(a)<<endl; //This works!
    cout<<toString(fa)<<endl; // This not works!
    return(0);
}

并且在我的模板结构上得到编译错误。错误只发生在我的Foo结构上。

stud1mTRPOlabsv3experimentmain.cpp||In instantiation of 'std::string toString(const T&) [with T = Foo<int>; std::string = std::basic_string<char>]':|
stud1mTRPOlabsv3experimentmain.cpp|59|required from here|
stud1mTRPOlabsv3experimentmain.cpp|19|error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'|
c:program filescodeblocksmingwbin..libgccmingw324.7.1includec++ostream|600|error:   initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Foo<int>]'|
||=== Build finished: 2 errors, 2 warnings (0 minutes, 1 seconds) ===|

请帮我把它修好。

我认为原因是<<运算符定义不正确。

提前谢谢!

问题是您的运算符<<c作为非常数引用,因此它无法绑定到toString()中使用的const T&。更改操作员如下:

template <class Num>
ostream &operator<< (ostream &output, const Foo<Num> &c)
{
    output<<"Foo("<<c.X<<","<<c.Y<<")";
    return output;
};