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: Roger Leigh <rleigh@…> 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:1 by James E. King, III, 5 years ago

In both Linux (libc 2.24) and Windows (Visual Studio 2015, 2017),

   printf("%s", nullptr);
 or
   printf("%s", 0);

result in the string:

(null)

Perhaps Boost.Format should do the same thing?

Last edited 5 years ago by James E. King, III (previous) (diff)

comment:2 by James E. King, III, 5 years ago

Owner: changed from Samuel Krempp to James E. King, III
Status: newassigned

comment:3 by James E. King, III, 5 years ago

Milestone: To Be DeterminedBoost 1.66.0
Resolution: wontfix
Status: assignedclosed

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

Note: See TracTickets for help on using tickets.