Integrating "explicit" Keyword into Library 26-Jan-95 ------------------------------------------- X3J16/95-0024 by Nathan Myers, myersn@roguewave.com WG21/N0624 Rogue Wave Software At the Valley Forge meeting I accepted responsibility for identifying where in the Standard Library the keyword "explicit" should be added to constructors for the standard classes. If the other proposal, for explicit operator conversions, is approved it will need to be integrated separately. To prevent conversion problems (see the Appendix for an example), in addition to marking particular constructors explicit, I recommend adding to section 17.3.4.4, a footnote: "An implementation which adds a constructor from a primitive type, a standard class, or a pointer or reference to any such type, breaks a demonstrable subset of well-formed programs." I expect the exception hierarchy to change radically at Austin, so I will not go into detail on Clause 19. All one-argument constructors for exception types should be marked "explicit". In Clause 20, the following one-argument constructors are defined: unary_negate(const Predicate&); binary_negate(const Predicate&); pointer_to_unary_function(Result (*f)(Arg)); pointer_to_binary_function(Result (*f)(Arg1, Arg2)); raw_storage_iterator(OutputIterator i); None of these needs to be an automatic conversion; all should be marked "explicit". In Clause 21, Strings, the following one-argument constructors appear: basic_string(const charT* s); basic_string(charT c, size_t rep = 1); The second constructor should be explicit, the first not. Integrating "explicit" Keyword into Library 26-Jan-95 Page 2 of 5 ------------------------------------------- 95-0024/N0624 In Clause 22, Localization, I find: locale(const char* std_name); ctype(size_t refs = 0); ctype(size_t refs = 0, /* more default args */) ctype_byname(const char* std_name, size_t refs = 0); num_get(size_t refs = 0); num_put(size_t refs = 0); numpunct(size_t refs = 0); numpunct_byname(const char* std_name, size_t refs = 0); collate(size_t refs = 0); collate_byname(const char* std_name, size_t refs = 0); codecvt(size_t refs = 0); codecvt_byname(const char* std_name, size_t refs = 0); time_get(size_t refs = 0); time_get_byname(const char* std_name, size_t refs = 0); time_put(size_t refs = 0); time_put_byname(const char* std_name, size_t refs = 0); money_get(size_t refs = 0); money_get_byname(const char* std_name, size_t refs = 0); money_put(size_t refs = 0); money_put_byname(const char* std_name, size_t refs = 0); moneypunct(size_t refs = 0); moneypunct_byname(const char* std_name, size_t refs = 0); messages(size_t refs = 0); messages_byname(const char* std_name, size_t refs = 0); All should be marked "explicit". In Clause 23, Containers, I find: bits(unsigned long val); bits(const string& str, size_t pos = 0, size_t n = NPOS); vector(size_type n, const T& value = T()); list(size_type n, const T& value = T()); deque(size_type n, const T& value = T()); priority_queue(const Compare& x = Compare()); set(const Compare& x = Compare()); multiset(const Compare& x = Compare()); map(const Compare& x = Compare()); multimap(const Compare& x = Compare()); All should be marked "explicit", except maybe the first. (p.s. shouldn't the second be parameterized on character type?) Integrating "explicit" Keyword into Library 26-Jan-95 Page 3 of 5 ------------------------------------------- 95-0024/N0624 In Clause 24, Iterators, I find: reverse_bidirectional_iterator(BidirectionalIterator x); reverse_iterator(RandomAccessIterator x); back_insert_iterator(Container& x); front_insert_iterator(Container& x); istream_iterator(istream& s); ostream_iterator(ostream& s); istreambuf_iterator(istream& s); istreambuf_iterator(streambuf* s); ostreambuf_iterator(ostream& s); ostreambuf_iterator(streambuf* s); I believe the first four should be marked "explicit". The stream iterators should remain as implicit conversions. In Clause 25, Algorithms, I find no constructors. In Clause 26, Numerics, many changes have occurred, and I don't have an up-to-date copy. As I recall, we made complex (what may become basic_complex) a template, and defined specializations for the built-in types float, double, and long double. The specializations were to contain conversions for the other built-in types. I shall only note here that the intention was that narrowing conversions were to be marked "explicit", but other auto-conversions permitted. For the case of val_array, I find: val_array(const slice_array&); val_array(const gslice_array&); val_array(const mask_array&); val_array(const indirect_array&); I think all these constructors should be marked the same way, explicit or not. Otherwise I do not have a recommendation, and I defer to numerics experts. Integrating "explicit" Keyword into Library 26-Jan-95 Page 4 of 5 ------------------------------------------- 95-0024/N0624 In Clause 27, Input/output, I find: streampos(streamoff off = 0); /* if retained */ basic_ios::failure(const string& what); /* follows Clause 19 */ basic_ios(basic_streambuf* sb); basic_istream(basic_streambuf* sb); strstreambuf(streamsize = 0); istrstream(const char_type* s); basic_stringbuf(basic_ios::openmode = ...); basic_stringbuf(const basic_string& s, basic_ios::openmode = ...); basic_istringstream(basic_ios::openmode = ...); basic_istringstream(const basic_string& s, basic_ios::openmode = ...); basic_ostringstream(basic_ios::openmode = ...); basic_ostringstream(const basic_string& s, basic_ios::openmode = ...); basic_ifstream(const char* s, openmode mode = in); basic_ofstream(const char* s, openmode mode = out); basic_stdiobuf(FILE* = 0); /* if retained */ All these constructors should be marked "explicit". Appendix -------- To understand the need for the restriction on implicit conversion extensions, consider the example: // Happysoft(tm) implementation headers class string { ... operator const char*(); // ah, for the old days, when chars were chars }; class complex { // oh, those good old days, when classes were classes :-) double x, y; public: complex(double, double); // a standard constructor complex(const string&); // a handy Happysoft(tm) extension }; Integrating "explicit" Keyword into Library 26-Jan-95 Page 5 of 5 ------------------------------------------- 95-0024/N0624 // user code -- a conforming program void f(const char*); //1 void f(complex); //2 string s; ... f(s); // supposed to call //1, but Happysoft(tm) compiler reports // ambiguity. This handy Happysoft(tm) extension has broken the user's program. Examples of quietly broken behavior are probably easy to invent. I'm not certain that the proposed restriction goes far enough, but it's a beginning.