Boost C++ Libraries: Ticket #7971: [C++11] Boost::Format doesn't like to be fed nullptr/std::nullptr_t https://svn.boost.org/trac10/ticket/7971 <p> As the following code example shows, boost::format is not happy being fed a C++11 nullptr. It would be nice if it could cope with this as a valid, but null, argument, e.g. equivalent to "", i.e. no output but a valid argument. I've done this in my own code as a workaround for now by specialising for std::nullptr_t and then feeding it "" instead. This might not be an issue with boost::format itself if this should be done elsewhere e.g. lexical_cast. </p> <p> Regards, Roger </p> <pre class="wiki">#include &lt;boost/format.hpp&gt; #include &lt;string&gt; int main() { boost::format fmt("%1% %2% %3%\n"); fmt % std::string("String") % 543 % nullptr; } </pre><p> ==&gt; </p> <pre class="wiki">% g++ -std=c++11 -o test test.cc In file included from /usr/include/boost/format.hpp:49:0, from test.cc:1: /usr/include/boost/format/feed_args.hpp: In instantiation of ‘void boost::io::detail::put_last(std::basic_ostream&lt;_CharT, _Traits&gt;&amp;, const T&amp;) [with Ch = char; Tr = std::char_traits&lt;char&gt;; T = std::nullptr_t]’: /usr/include/boost/format/feed_args.hpp:159:13: required from ‘void boost::io::detail::put(T, const boost::io::detail::format_item&lt;Ch, Tr, Alloc&gt;&amp;, typename boost::basic_format&lt;Ch, Tr, Alloc&gt;::string_type&amp;, typename boost::basic_format&lt;Ch, Tr, Alloc&gt;::internal_streambuf_t&amp;, boost::io::detail::locale_t*) [with Ch = char; Tr = std::char_traits&lt;char&gt;; Alloc = std::allocator&lt;char&gt;; T = std::nullptr_t&amp;; typename boost::basic_format&lt;Ch, Tr, Alloc&gt;::string_type = std::basic_string&lt;char&gt;; typename boost::basic_format&lt;Ch, Tr, Alloc&gt;::internal_streambuf_t = boost::io::basic_altstringbuf&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;; boost::io::detail::locale_t = std::locale]’ /usr/include/boost/format/feed_args.hpp:253:17: required from ‘void boost::io::detail::distribute(boost::basic_format&lt;Ch, Tr, Alloc&gt;&amp;, T) [with Ch = char; Tr = std::char_traits&lt;char&gt;; Alloc = std::allocator&lt;char&gt;; T = std::nullptr_t&amp;]’ /usr/include/boost/format/feed_args.hpp:263:9: required from ‘boost::basic_format&lt;Ch, Tr, Alloc&gt;&amp; boost::io::detail::feed(boost::basic_format&lt;Ch, Tr, Alloc&gt;&amp;, T) [with Ch = char; Tr = std::char_traits&lt;char&gt;; Alloc = std::allocator&lt;char&gt;; T = std::nullptr_t&amp;]’ /usr/include/boost/format/format_class.hpp:64:74: required from ‘boost::basic_format&lt;Ch, Tr, Alloc&gt;&amp; boost::basic_format&lt;Ch, Tr, Alloc&gt;::operator%(const T&amp;) [with T = std::nullptr_t; Ch = char; Tr = std::char_traits&lt;char&gt;; Alloc = std::allocator&lt;char&gt;; boost::basic_format&lt;Ch, Tr, Alloc&gt; = boost::basic_format&lt;char&gt;]’ test.cc:9:39: required from here /usr/include/boost/format/feed_args.hpp:100:9: error: ambiguous overload for ‘operator&lt;&lt;’ in ‘os &lt;&lt; x’ /usr/include/boost/format/feed_args.hpp:100:9: note: candidates are: In file included from /usr/include/boost/format/detail/compat_workarounds.hpp:60:0, from /usr/include/boost/format.hpp:27, from test.cc:1: /usr/include/c++/4.7/ostream:106:7: note: std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp; (*)(std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp;)) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type = std::basic_ostream&lt;char&gt;] /usr/include/c++/4.7/ostream:115:7: note: std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;::__ios_type&amp; (*)(std::basic_ostream&lt;_CharT, _Traits&gt;::__ios_type&amp;)) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type = std::basic_ostream&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__ios_type = std::basic_ios&lt;char&gt;] /usr/include/c++/4.7/ostream:125:7: note: std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::ios_base&amp; (*)(std::ios_base&amp;)) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type = std::basic_ostream&lt;char&gt;] /usr/include/c++/4.7/ostream:172:7: note: std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(bool) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type = std::basic_ostream&lt;char&gt;] /usr/include/c++/4.7/ostream:243:7: note: std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(const void*) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__ostream_type = std::basic_ostream&lt;char&gt;] In file included from /usr/include/c++/4.7/ostream:607:0, from /usr/include/boost/format/detail/compat_workarounds.hpp:60, from /usr/include/boost/format.hpp:27, from test.cc:1: /usr/include/c++/4.7/bits/ostream.tcc:121:5: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;::__streambuf_type*) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; std::basic_ostream&lt;_CharT, _Traits&gt;::__streambuf_type = std::basic_streambuf&lt;char&gt;] In file included from /usr/include/boost/format/detail/compat_workarounds.hpp:60:0, from /usr/include/boost/format.hpp:27, from test.cc:1: /usr/include/c++/4.7/ostream:600:5: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;&amp;&amp;, const _Tp&amp;) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;; _Tp = std::nullptr_t] &lt;near match&gt; /usr/include/c++/4.7/ostream:600:5: note: no known conversion for argument 1 from ‘std::basic_ostream&lt;char&gt;’ to ‘std::basic_ostream&lt;char&gt;&amp;&amp;’ /usr/include/c++/4.7/ostream:546:5: note: std::basic_ostream&lt;char, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;char, _Traits&gt;&amp;, const unsigned char*) [with _Traits = std::char_traits&lt;char&gt;] /usr/include/c++/4.7/ostream:541:5: note: std::basic_ostream&lt;char, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;char, _Traits&gt;&amp;, const signed char*) [with _Traits = std::char_traits&lt;char&gt;] /usr/include/c++/4.7/ostream:528:5: note: std::basic_ostream&lt;char, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;char, _Traits&gt;&amp;, const char*) [with _Traits = std::char_traits&lt;char&gt;] In file included from /usr/include/c++/4.7/ostream:607:0, from /usr/include/boost/format/detail/compat_workarounds.hpp:60, from /usr/include/boost/format.hpp:27, from test.cc:1: /usr/include/c++/4.7/bits/ostream.tcc:323:5: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;&amp;, const char*) [with _CharT = char; _Traits = std::char_traits&lt;char&gt;] </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7971 Trac 1.4.3 James E. King, III Thu, 12 Oct 2017 19:44:55 GMT <link>https://svn.boost.org/trac10/ticket/7971#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7971#comment:1</guid> <description> <p> In both Linux (libc 2.24) and Windows (Visual Studio 2015, 2017), </p> <pre class="wiki"> printf("%s", nullptr); or printf("%s", 0); </pre><p> result in the string: </p> <pre class="wiki">(null) </pre><p> Perhaps Boost.Format should do the same thing? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>James E. King, III</dc:creator> <pubDate>Fri, 13 Oct 2017 18:36:42 GMT</pubDate> <title>owner, status changed https://svn.boost.org/trac10/ticket/7971#comment:2 https://svn.boost.org/trac10/ticket/7971#comment:2 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Samuel Krempp</span> to <span class="trac-author">James E. King, III</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket James E. King, III Fri, 13 Oct 2017 18:40:48 GMT status, milestone changed; resolution set https://svn.boost.org/trac10/ticket/7971#comment:3 https://svn.boost.org/trac10/ticket/7971#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.66.0</span> </li> </ul> <p> On further review, this is a C++ standards issue and not a Boost.Format concern. </p> <p> See: </p> <p> <a class="ext-link" href="http://cplusplus.github.io/LWG/lwg-defects.html#2221"><span class="icon">​</span>http://cplusplus.github.io/LWG/lwg-defects.html#2221</a> </p> <p> A workaround is to define your own std::ostream operator for your program to work with a nullptr - it is not the responsibility of Boost.Format to do this for a native type. Doing so would lead to compatibility issues later if the standard changes requiring libraries to implement it - it would become ambiguous again. </p> <p> Additional discussion can be found on stack overflow which has suggestions for a workaround: </p> <p> <a class="ext-link" href="https://stackoverflow.com/questions/31164961/operator-stream-output-for-nullptr"><span class="icon">​</span>https://stackoverflow.com/questions/31164961/operator-stream-output-for-nullptr</a> </p> Ticket