为什么boost::format不能直接转换为std::string?

12

以下是不可能的:

std::string s = boost::format("%d") % 1; // error

你需要显式地调用 str() 方法:

std::string s = (boost::format("%d") % 1).str(); // OK

这只是语法糖,为什么不添加转换呢?


重载 % 不够糟糕吗? :) - jrok
2
我不确定你在这里寻找什么样的答案。你是在问是否有任何语义问题阻止Boost实现这样的事情吗?还是你只是说,“他们应该这样做。” - Nicol Bolas
1
我正在努力理解语义问题。我通常认为boost库设计得很好。 - mr_georg
1
隐式转换有时很方便,但也会在你真正不想要转换时隐藏错误。Boost遵循std::string和std::stringstream的模型,它们都不提供对其内容类型的隐式转换。 - Bo Persson
1
@jrok 重载 '%' 有什么不好的呢? - BigBoss
2
@jrok 这里有一个很好的理由:http://www.boost.org/doc/libs/1_51_0/libs/format/doc/choices.html - pmr
2个回答

11

我认为这是与 std::stringstream 相同的原因,在这种情况下,您还应该使用 .str() 将流转换为字符串,并对 boost::formatter 采用相同的方法。原因如下:

std::string s1 = "Hello ", s2 = "World";
format("%s.") % s1 + s2;
现在,如果`boost::formatter`可以隐式转换为`std::string`,那么它会产生"Hello .World",因为`format("%s.") % s1`将被转换为"Hello .",然后它将被隐式转换为`std::string`并使用`operator+`与`s2`相加。但是可能大多数程序员希望得到"Hello World.",这将是一个错误和混淆的来源。但是,在不存在隐式转换的情况下,编译器将生成错误(因为没有`boost::formatter`和`std::string`的`operator+`),您需要将其更正为`format("%s.") % (s1 + s2)`或`str( format("%s.") % s1 ) + s2`。

9

如果隐式转换可能会引发异常,则不是一件好事。默认情况下,如果向format提供的参数少于所需参数,则转换为字符串将抛出异常。例如:

std::string f()
{
   boost::format fmt("%d");
   // forgot to feed an argument
   std::string s = fmt;  // throws boost::io::too_few_args
   widget.set_title( fmt );  // throws boost::io::too_few_args
   return fmt;  // throws boost::io::too_few_args
}

这样的隐式类型转换使得很难发现和分析代码中可能抛出异常的部分。但是,显式的 .str() 调用提供了这种可能异常的提示,在确保周围代码的异常安全性时更容易,并且(在这种特定情况下)提示再次仔细检查前面的代码,以预防首先发生该异常。


这两个答案(包括BigBoss的答案)都给出了不进行隐式转换的好理由。但是我只能接受一个 :-) - mr_georg

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