【问题标题】:Is there a warning free template function to convert basic types to string是否有无警告模板函数可将基本类型转换为字符串
【发布时间】:2010-11-16 15:28:48
【问题描述】:

我想提供一个将大多数基本类型转换为字符串的模板化函数。 到目前为止,我想出的最好的方法如下:

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;
     };

anyToString 和类似函数的问题是使用 gcc 版本 4.4.3 -Wall -Wexta -Werror 编译时产生歧义警告 "ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second"

据我所知,警告的原因在于调用

这些歧义主要是由其他模板产生的,如下所示:

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

但它们还有其他优点,例如适用于多种流类型。 所以我想保留它们。如果我将第二个模板变成一个简单的方法,例如ostream 歧义已被清除,但我正在寻找某事。这允许保留两个模板。 是否有一个通用函数可以提供相同的简单性而不会使用所描述的选项生成警告? 如果没有,本地禁用发出的警告的最佳方法是什么?

【问题讨论】:

  • 嗯。你能添加一个你如何使用这个模板的例子吗?
  • @Oli Charlesworth:添加了一个用法示例
  • @Martin,当你说“那些选项”时,你指的是什么选项?
  • boost::lexical_cast&lt;std::string&gt;() 不适合你? (它不会解决歧义警告,但滚动你自己的“转换”功能似乎是多余的)
  • @Matthieu: boost::lexical_cast 有效。我到现在都不知道

标签: c++ templates ambiguous


【解决方案1】:

您似乎会从这样的场景中收到这样的消息:

#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 &lt;&lt; angle.deg(); 可能会返回一个对ostream 的引用,该引用不能被隐式向下转换回stringstream 引用。

【讨论】:

  • 好例子,我在描述中添加了真正的邪恶来源,但你的例子地址一样。 -pedantic 在我的代码上看起来不错,但我使用了几个 qt4 库,这些库在警告/错误生成方面是一场噩梦
  • @UncleBens:很好地解决了operator&lt;&lt; 的模板问题,因此它只与以类似方式定义的运算符兼容。
  • @UncleBens:我认为模板化的
  • @Martin:自己尝试一下。这些类型的现有operator&lt;&lt; 仍返回ostream&amp;。为标准库流重载operator&lt;&lt; 的正确方法是为ostream&amp; 这样做
  • @UncleBens(有点吹毛求疵):std::basic_ostream&lt;Char, Traits&gt; 的过载比std::ostream 更好:template&lt;typename Char, typename Traits&gt; std::basic_ostream&lt;Char, Traits&gt;&amp; operator&lt;&lt;(std::basic_ostream&lt;Char, Traits&gt;&amp; stream, const Type&amp; object) { }
【解决方案2】:

据我所知,您的编译器为此目的支持#pragma - 我知道 VC++ 支持。但是,您也可以只使用 boost::lexical_cast。

【讨论】:

  • boost::lexical_cast 在我的回答中展示的一组类似的重载失败并显示相同的消息(除了它使用stringstream)。
  • boost::lexical cast 可以解决问题,但我必须为这个和其他将使用该模板的人安装并​​包含 boost。
猜你喜欢
  • 2019-06-14
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2016-07-14
  • 2011-12-29
  • 1970-01-01
  • 2015-05-24
相关资源
最近更新 更多