Opened 10 years ago
Closed 5 years ago
#7971 closed Bugs (wontfix)
[C++11] Boost::Format doesn't like to be fed nullptr/std::nullptr_t
Reported by: | Owned by: | James E. King, III | |
---|---|---|---|
Milestone: | Boost 1.66.0 | Component: | format |
Version: | Boost 1.50.0 | Severity: | Problem |
Keywords: | Cc: |
Description
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.
Regards, Roger
#include <boost/format.hpp> #include <string> int main() { boost::format fmt("%1% %2% %3%\n"); fmt % std::string("String") % 543 % nullptr; }
==>
% 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<_CharT, _Traits>&, const T&) [with Ch = char; Tr = std::char_traits<char>; 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<Ch, Tr, Alloc>&, typename boost::basic_format<Ch, Tr, Alloc>::string_type&, typename boost::basic_format<Ch, Tr, Alloc>::internal_streambuf_t&, boost::io::detail::locale_t*) [with Ch = char; Tr = std::char_traits<char>; Alloc = std::allocator<char>; T = std::nullptr_t&; typename boost::basic_format<Ch, Tr, Alloc>::string_type = std::basic_string<char>; typename boost::basic_format<Ch, Tr, Alloc>::internal_streambuf_t = boost::io::basic_altstringbuf<char, std::char_traits<char>, std::allocator<char> >; 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<Ch, Tr, Alloc>&, T) [with Ch = char; Tr = std::char_traits<char>; Alloc = std::allocator<char>; T = std::nullptr_t&]’ /usr/include/boost/format/feed_args.hpp:263:9: required from ‘boost::basic_format<Ch, Tr, Alloc>& boost::io::detail::feed(boost::basic_format<Ch, Tr, Alloc>&, T) [with Ch = char; Tr = std::char_traits<char>; Alloc = std::allocator<char>; T = std::nullptr_t&]’ /usr/include/boost/format/format_class.hpp:64:74: required from ‘boost::basic_format<Ch, Tr, Alloc>& boost::basic_format<Ch, Tr, Alloc>::operator%(const T&) [with T = std::nullptr_t; Ch = char; Tr = std::char_traits<char>; Alloc = std::allocator<char>; boost::basic_format<Ch, Tr, Alloc> = boost::basic_format<char>]’ test.cc:9:39: required from here /usr/include/boost/format/feed_args.hpp:100:9: error: ambiguous overload for ‘operator<<’ in ‘os << 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<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] /usr/include/c++/4.7/ostream:115:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>; std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>] /usr/include/c++/4.7/ostream:125:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] /usr/include/c++/4.7/ostream:172:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] /usr/include/c++/4.7/ostream:243:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 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<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>] 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<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::nullptr_t] <near match> /usr/include/c++/4.7/ostream:600:5: note: no known conversion for argument 1 from ‘std::basic_ostream<char>’ to ‘std::basic_ostream<char>&&’ /usr/include/c++/4.7/ostream:546:5: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const unsigned char*) [with _Traits = std::char_traits<char>] /usr/include/c++/4.7/ostream:541:5: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const signed char*) [with _Traits = std::char_traits<char>] /usr/include/c++/4.7/ostream:528:5: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*) [with _Traits = std::char_traits<char>] 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<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*) [with _CharT = char; _Traits = std::char_traits<char>]
Change History (3)
comment:2 by , 5 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 5 years ago
Milestone: | To Be Determined → Boost 1.66.0 |
---|---|
Resolution: | → wontfix |
Status: | assigned → closed |
On further review, this is a C++ standards issue and not a Boost.Format concern.
See:
http://cplusplus.github.io/LWG/lwg-defects.html#2221
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.
Additional discussion can be found on stack overflow which has suggestions for a workaround:
https://stackoverflow.com/questions/31164961/operator-stream-output-for-nullptr
In both Linux (libc 2.24) and Windows (Visual Studio 2015, 2017),
result in the string:
Perhaps Boost.Format should do the same thing?