Opened 7 years ago

Last modified 7 years ago

#6160 assigned Feature Requests

support for (istream >> array < char >)

Reported by: giecrilj@… Owned by: Marshall Clow
Milestone: To Be Determined Component: array
Version: Boost 1.44.0 Severity: Cosmetic
Keywords: Cc:

Description

  1. array < T > is a replacement for T []
  2. the standard library provides the syntax (istream >> char []) and (ostream << char const [])
  3. Currently, (istream >> array < char >) does not mean anything
  4. this functionality cannot be simulated even with std:: copy_n < istreambuf_iterator > without manual termination and much verbosity

My implementation

#include <boost/array.hpp>      /* for ::boost:: array */
#include <boost/version.hpp>

#if +BOOST_VERSION <= 0313720
#include <iomanip>      /* for ::std:: setw */
namespace boost 
{ 
/* helper classes to prevent ambiguity in matching array < char > */
namespace detail_
{ 
/* normally, other char for every character type is char */
  template < class P_C > class other_char { public: typedef char type; }; 
/* but other_char is undefined for char */
  template <> class other_char < char > {}; 
/* class same_stream fails for istream */
  template 
  < class P_S, 
    class P_C = typename other_char < typename P_S:: char_type >:: type >
class same_stream { public: typedef P_S stream; }; }
/* template input */
  template < class P_C, class P_T, ::std:: size_t P_N > 
  static inline ::std:: basic_istream < P_C, P_T >
&operator >> 
  (::std:: basic_istream < P_C, P_T > &p_s, ::boost:: array < P_C, P_N > &p_a) 
  { return p_s >> ::std:: setw (p_a. static_size) >> p_a. data (); } 
/* character input, disabled for type char to avoid ambiguity */
  template < class P_C, class P_T, ::std:: size_t P_N > 
  static inline typename
  detail_:: same_stream 
< ::std:: basic_istream < P_C, P_T > >:: stream
&operator >> 
  (::std:: basic_istream < P_C, P_T > &p_s, 
   ::boost:: array < char, P_N > &p_a) 
  { return p_s >> ::std:: setw (p_a. static_size) >> p_a. data (); } 
/* template output */
  template < class P_C, class P_T, ::std:: size_t P_N > 
  static inline ::std:: basic_ostream < P_C, P_T > 
  &operator << 
(::std:: basic_ostream < P_C, P_T > &p_s, 
 ::boost:: array < P_C, P_N > const &p_a) { return p_s << p_a. begin (); }
/* character output, disabled for type char */
  template < class P_C, class P_T, ::std:: size_t P_N > 
  static inline 
typename detail_:: same_stream < ::std:: basic_ostream < P_C, P_T > >:: stream
  &operator << 
(::std:: basic_ostream < P_C, P_T > &p_s, 
 ::boost:: array < char, P_N > const &p_a) 
{ return p_s << p_a. begin (); }}
#endif  /* BOOST_VERSION */

#include <cstdlib>      /* for EXIT_SUCCESS */
#include <cstdio>       /* for BUFSIZ */
#include <iostream>     /* for ::std:: cin */

int main () 
{ // char (&x) [+BOOST_VERSION] = 0;
#ifdef ARRAY_IN_NATIVE
/* native code */
char t [+BUFSIZ]; 
 return 
   ::std:: cin >> ::std:: setw (+BUFSIZ) >> t && ::std:: cout << t << '\n'? 
+EXIT_SUCCESS: +EXIT_FAILURE; 
#else /* ARRAY_IN_NATIVE */
/* equivalent Boost code */
 ::boost:: array < char, +BUFSIZ > t; 
/* check that character input compiles for wchar_t */
 (void) sizeof (std:: wcin >> t);
 return 
::std:: cin >> t && ::std:: cout << t << '\n'? +EXIT_SUCCESS: +EXIT_FAILURE;
#endif /* ARRAY_IN_NATIVE */
}

Change History (10)

comment:1 Changed 7 years ago by Sebastian Redl

the standard library provides the syntax (istream >> char []) and (ostream << char const [])

No, it provides istream >> char* and ostream << char const*. As such, you can quite easily use the c_array() and data() members to get pointers to the data: istream >> ar.c_array() and ostream << ar.data().

comment:2 in reply to:  1 Changed 7 years ago by ne01026@…

Replying to cornedbee:

the standard library provides the syntax (istream >> char []) and (ostream << char const [])

No, it provides istream >> char* and ostream << char const*. As such, you can quite easily use the c_array() and data() members to get pointers to the data: istream >> ar.c_array() and ostream << ar.data().

The call istream >> ar.c_array () invites buffer overflow and undefined behaviour. If it were that simple, I would not bother writing so many words here.

comment:3 Changed 7 years ago by Marshall Clow

Status: newassigned

I don't see the difference between: istream >> char * , istream >> char [] and istream >> boost::array<char> in terms of buffer overflow prevention.

It seems to me that in each case, it is the responsibility of the person providing the input to make sure that the input fits into the provided buffer.

Am I missing something here?

comment:4 Changed 7 years ago by ne01026@…

char [] has unknown length, array < char > has known length, therefore >> array is safer than >> char [], and my code, attached, q.v., uses this information to prevent buffer overflow.

comment:5 in reply to:  3 Changed 7 years ago by ne01026@…

Replying to marshall:

It seems to me that in each case, it is the responsibility of the person providing the input to make sure that the input fits into the provided buffer.

This is not possible for general streams, unless your machine happens to be clairvoyant.

comment:6 in reply to:  4 ; Changed 7 years ago by Marshall Clow

Replying to ne01026@…:

char [] has unknown length, array < char > has known length, therefore >> array is safer than >> char [], and my code, attached, q.v., uses this information to prevent buffer overflow.

char [] has known length - sizeof is your friend here.

I see where your code is using the length to prevent a buffer overflow - but doing that at every stream extraction is error-prone, at best. It seems to me that (famous last words) that if this were to be implemented, it should never overflow the bounds of the array.

Do you know if this was considered for std::array?

comment:7 in reply to:  6 ; Changed 7 years ago by ne01026@…

Replying to marshall:

Replying to ne01026@…:

char [] has unknown length, array < char > has known length, therefore >> array is safer than >> char [], and my code, attached, q.v., uses this information to prevent buffer overflow.

char [] has known length - sizeof is your friend here.

sizeof (char []) is undefined.

I see where your code is using the length to prevent a buffer overflow - but doing that at every stream extraction is error-prone, at best. It seems to me that (famous last words) that if this were to be implemented, it should never overflow the bounds of the array.

The extraction operator will not extract more characters than the array length, minus one, so where is the error?

Do you know if this was considered for std::array?

I do not know; however, given that std takes from boost and not the other way round, I decided to put it here first. At least, the thing seems obvious and straighforward to me. The standard library has special semantics for (native) character arrays, and so should we.

I tried to discuss the matter at #boost and I was told to file an enhancement, so here it is.

comment:8 in reply to:  7 ; Changed 7 years ago by Marshall Clow

Replying to ne01026@…:

Replying to marshall:

Replying to ne01026@…:

char [] has unknown length, array < char > has known length, therefore >> array is safer than >> char [], and my code, attached, q.v., uses this information to prevent buffer overflow.

char [] has known length - sizeof is your friend here.

sizeof (char []) is undefined.

Sorry - I was imprecise: char [N] has size N for all N > 0

Do you know if this was considered for std::array?

I do not know; however, given that std takes from boost and not the other way round, I decided to put it here first. At least, the thing seems obvious and straighforward to me. The standard library has special semantics for (native) character arrays, and so should we.

I tried to discuss the matter at #boost and I was told to file an enhancement, so here it is.

And I'm glad that you did - and now we are discussing it.

BTW - if this were to become part of boost, it would be more complicated. You should be able to extract from std::wcin to a boost::array<wchar_t>, for example.

comment:9 in reply to:  8 ; Changed 7 years ago by ne01026@…

Replying to marshall:

Replying to ne01026@…:

Replying to marshall:

Replying to ne01026@…:

char [] has unknown length, array < char > has known length, therefore >> array is safer than >> char [], and my code, attached, q.v., uses this information to prevent buffer overflow.

char [] has known length - sizeof is your friend here.

sizeof (char []) is undefined.

Sorry - I was imprecise: char [N] has size N for all N > 0

Unfortunately, the standard library does not provide istream >> char (&) [N] as some older compilers are unable to match against such a template, so the best we can do is to define this thing for array.

BTW - if this were to become part of boost, it would be more complicated. You should be able to extract from std::wcin to a boost::array<wchar_t>, for example.

I already do, that is why the code is so ugly :-(

comment:10 in reply to:  9 Changed 7 years ago by Marshall Clow

BTW - if this were to become part of boost, it would be more complicated. You should be able to extract from std::wcin to a boost::array<wchar_t>, for example.

I already do, that is why the code is so ugly :-(

I apologize. I clearly did not read your code closely enough.

Note: See TracTickets for help on using tickets.