有没有一个无警告的模板函数可以将基本类型转换为字符串?

3
我希望提供一个模板函数,将大多数基本类型转换为字符串。 到目前为止,我想到的最好方法如下:
template<typename T> inline std::string anyToString(const T& var) {
  std::ostringstream o;
  o << var;
  return o.str();
}

该函数可以用于以下方面:

 class TimeError:public std::runtime_error{
     public:
       explicit TimeError(int time):std::runtime_error(anyToString(time)),
       mTime(time){};
     protected:
       int mTime;
     };

任何toString和类似函数的问题在于使用gcc版本4.4.3 -Wall -Wextra -Werror编译时会生成歧义警告。"ISO C ++表示,即使第一个最差的转换优于第二个最差的转换,这些都是模棱两可的。"据我所知,警告的原因在于调用<<时的隐式转换可能性。这些歧义主要由其他模板生成,如下所示:
  template<typename T>
    T& operator<<(T& out, const SymRad& angle){
    return out << angle.deg();
  }

但是它们有其他优点,比如可以适用于多种流类型。因此,我希望保留它们。如果我将第二个模板转换为普通方法(例如ostream),则可以消除歧义,但我正在寻找一种方法,可以同时保留两个模板。 是否有一种通用函数,可以提供相同的简洁性,并使用所描述的选项而不生成警告? 如果没有,最好的方法是在本地禁用发出的警告。


2
嗯,你能添加一个使用这个模板的例子吗? - Oliver Charlesworth
@Oli Charlesworth:添加了一个使用示例。 - Martin
@ Martin,当你说“那些选项”时,你指的是哪些选项? - Rob Kennedy
boost::lexical_cast<std::string>() 对你没用吗?(它不能解决歧义警告,但自己编写“转换”函数似乎是多余的) - Matthieu M.
@Matthieu:boost::lexical_cast 可以使用。我之前不知道。 - Martin
@Rob:转换选项产生了歧义,我的表述不清楚,已经进行了更改。 - Martin
2个回答

2

看起来您会在以下情况下收到这样的消息:

#include <sstream>
#include <string>
#include <iostream>

struct Y {};
struct X
{
    operator Y() const {return Y(); }
};

std::ostream& operator<< (std::ostream& os, X) { return os << "X"; }
std::ostream& operator<< (std::ostringstream& os, Y) { return os << "Y"; }

template<typename T> inline std::string anyToString(const T& var) {
  std::ostringstream o;
  o << var;
  return o.str();
}

int main()
{
    std::cout << anyToString(X()) << '\n';
}

我建议使用-pedantic标志。GCC通过编译器扩展支持它,而其他编译器则会直接报错。


至于你的补充:

  template<typename T>
    T& operator<<(T& out, const SymRad& angle){
    return out << angle.deg();
  }

但是那些有其他的优点,比如适用多种流类型。

这实际上并不适用于多种流类型。例如,如果 Tstringstream,那么 out << angle.deg(); 可能会返回一个指向 ostream 的引用,该引用无法被隐式地强制转换回 stringstream 引用。


好的例子,我在描述中添加了真正的罪魁祸首,但你的例子也是一样的。-pedantic 在我的代码上看起来不错,但我使用了几个 qt4 库,这些库在警告/错误生成方面非常棘手。 - Martin
@UncleBens:关于operator<<的模板问题,你说得很对,它只能与以类似方式定义的运算符兼容。 - Matthieu M.
@UncleBens:我认为,模板化的<<运算符可以用于字符串流和文件流(std::ofstream和std::ostringstream)等情况。如果我错了,请纠正我。 - Martin
@Martin:自己试一下。对于这些类型,现有的 operator<< 仍然返回 ostream&。重载标准库流的正确方法是针对 ostream& 进行重载。 - UncleBens
@UncleBens(有点挑剔):比std::ostream更好的重载是std::basic_ostream<Char, Traits>template<typename Char, typename Traits> std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& stream, const Type& object) { } - Philipp

1

据我所知,您的编译器支持一个用于此目的的#pragma - 我知道VC++是这样的。不过,您也可以使用boost::lexical_cast。


boost::lexical_cast在相似的一组重载中会出现与我回答中演示的相同错误信息(只是它使用了stringstream)。 - UncleBens
boost::lexical_cast可以解决这个问题,不过我需要安装和包含boost库,其他使用该模板的人也需要这样做。 - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接