Are additional constructors for standard containers allowed?

  • Thread starter Alf P. Steinbach /Usenet
  • Start date
J

Juha Nieminen

Niels Dekker - no reply address said:
What do you mean by "possibly a const"? The following is still
ambiguous, according to the current Working Draft (N3126):

const int zeroConst = 0;
// bitset(unsigned long long) or bitset(const char*)?
std::bitset<5> bits(zeroConst);

Why would a const int be confused with a const char* by the compiler?
They are completely unrelated types.
 
A

Alf P. Steinbach /Usenet

* Juha Nieminen, on 05.09.2010 21:06:
Why would a const int be confused with a const char* by the compiler?
They are completely unrelated types.

Because a compile-time const integer of value 0, any integer type, converts
implicitly to nullpointer of any type.


Cheers & hth.,

- Alf
 
N

Niels Dekker - no reply address

Hope you like the proposed resolution :)
No. It doesn't support NULL as nullptr_t, and it has incorrect casts.

Personally I find it acceptable if std::bitset<N>(NULL) might yield a
compile error on some implementations. (But I'm unhappy about the fact that
the Working Draft (N3126) allows undefined behavior in this case.) Thanks
though, for your Wrapped<unsigned long long> based workaround.

Are those the casts, charT('0'), charT('1'), merely a problem for the EBCDIC
character encoding? I have to admit I don't know much about EBCDIC. Are
there any upcoming C++0x implementations expected to support EBCDIC?

Did the C++03 std::bitset support EBCDIC?

Kind regards,

Niels
 
J

Juha Nieminen

Alf P. Steinbach /Usenet said:
* Juha Nieminen, on 05.09.2010 21:06:

Because a compile-time const integer of value 0, any integer type, converts
implicitly to nullpointer of any type.

That sounds like a potential source of lots of problems. Who thought
it would be a good idea?

An int is not a pointer, even if that int happens to have the value 0.
 
A

Alf P. Steinbach /Usenet

* Juha Nieminen, on 07.09.2010 21:14:
That sounds like a potential source of lots of problems.

Not only potential... :)

And most everybody agree, and that's why 'nullptr_t' and 'nullptr' are
introduced in C++0x.

But of course, not without problems of its own, in particular backward
compatibility for the cases where NULL worked as /integer/ in earlier C++ code.

Who thought it would be a good idea?

The blame of original sin probably belongs to Dennis Ritchie.

At least, he originally developed C, and this conversion was there (although
only formally specified for the literal 0, of int type) already in early C.

K&R "The C Programming Language" 1976 Appendix A "C Reference Manual" §7.14:
"However, it is guaranteed that assignment of the constant 0 to a pointer will
produce a null pointer distinguishable from a pointer to any object".

An int is not a pointer, even if that int happens to have the value 0.

Hm.


Cheers,

- Alf
 
J

Juha Nieminen

Alf P. Steinbach /Usenet said:
Not only potential... :)

And most everybody agree, and that's why 'nullptr_t' and 'nullptr' are
introduced in C++0x.

But there's a difference between:

someFunction(0)

and:

const int zero = 0;
someFunction(zero);

The latter is unambiguously an int, not a pointer.
 
A

Alf P. Steinbach /Usenet

* Juha Nieminen, on 07.09.2010 21:59:
But there's a difference between:

someFunction(0)

and:

const int zero = 0;
someFunction(zero);

The latter is unambiguously an int, not a pointer.

Yes, I agree: the original sin was compounded in C++. :-(

What to do about it?

Various kludgy workarounds.


Cheers,

- Alf
 
J

James Kanze

But there's a difference between:


const int zero = 0;
someFunction(zero);
The latter is unambiguously an int, not a pointer.

No more so than the first. The argument in both cases is
a constant expression having type int, and evaluating to zero.

Of course, a compiler *could* do something special, depending on
the spelling. G++ does: if you use NULL in a context where an
integral type is expected, g++ generates a warning. (But it
doesn't warn if you use 0 in a context where a pointer is
expected.)
 
F

Francesco S. Carta

No more so than the first. The argument in both cases is
a constant expression having type int, and evaluating to zero.

Of course, a compiler *could* do something special, depending on
the spelling. G++ does: if you use NULL in a context where an
integral type is expected, g++ generates a warning. (But it
doesn't warn if you use 0 in a context where a pointer is
expected.)

That should depend on how you're compiling the source. At least in
MinGW, compiling in C++ mode, NULL is perfectly fine assigned to an int,
because NULL is defined as 0. Compiling in C mode it's another matter,
because NULL is defined as ((void*)0).

Interestingly, Stroustrup wrote that this is a case where the type
checking system in C is stricter than in C++.

[citation off the top of my head, it should be somewhere in the
"Siblings' rivalry" paper]
 
J

James Kanze

That should depend on how you're compiling the source.

There might be an option to turn it off. With no options, I get
the warning from g++ 4.1.1 (under Linux, the only version I have
handy at present).
At least in
MinGW, compiling in C++ mode, NULL is perfectly fine assigned to an int,
because NULL is defined as 0. Compiling in C mode it's another matter,
because NULL is defined as ((void*)0).

Then MinGW have modified g++ or the libraries somehow. Try the
following program:

#include <stddef.h>
#include <iostream>

#define S1(s) #s
#define S(s) S1(s)

int f(int i)
{
return i;
}

int
main()
{
std::cout << "NULL = \"" << S(NULL) << "\"\n";
std::cout << f(NULL) << '\n';
return 0;
}

Compiling (with simply g++ nullptr.cc) gives me:
nullptr.cc: In function 'int main()':
nullptr.cc:22: warning: passing NULL to non-pointer argument 1 of
'int f(int)'

And running:
NULL = "__null"
0

The C and C++ standards are actually fairly close in this
respect: the macro NULL must be defined as something specifying
a null pointer constant. And a null pointer constant is an
integral constant expression evaluating to 0; C also allows the
null pointer constant to be such an expression explicitly
converted to void*, but that's an innovation of the
C standard---in traditional C, and on most platforms I've seen,
NULL has been #define'd to 0 in C. (Of course, it can be
#define'd to anything that is a null pointer constant: "(1-1)",
"'\0'", "0L"... or even something like "__null", provided the
compiler ensures that __null is treated as a null pointer
constant.)
Interestingly, Stroustrup wrote that this is a case where the
type checking system in C is stricter than in C++.

I'd be surprised by that. The reason ((void*)0) is not allowed
as a null pointer constant in C++ is because unlike in C,
a void* doesn't implicitly to any other pointer type. (It's not
really a valid reason, since int's require compiler magic to
work as well; that compiler magic could have been extended to
((void*)0) as well.)
 
F

Francesco S. Carta

There might be an option to turn it off. With no options, I get
the warning from g++ 4.1.1 (under Linux, the only version I have
handy at present).


Then MinGW have modified g++ or the libraries somehow. Try the
following program:

#include<stddef.h>
#include<iostream>

#define S1(s) #s
#define S(s) S1(s)

int f(int i)
{
return i;
}

int
main()
{
std::cout<< "NULL = \""<< S(NULL)<< "\"\n";
std::cout<< f(NULL)<< '\n';
return 0;
}

Compiling (with simply g++ nullptr.cc) gives me:
nullptr.cc: In function 'int main()':
nullptr.cc:22: warning: passing NULL to non-pointer argument 1 of
'int f(int)'

And running:
NULL = "__null"
0

Same output but no warning at all here - don't ask me why, I have no
idea :-/

But I must correct myself, of course, because compiling with the default
settings, NULL gets defined as __null, as your test proved, in my setup.

An excerpt from stddef.h on my setup:

#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else /* C++ */
#define NULL 0
#endif /* C++ */
#endif /* G++ */
#endif /* NULL not defined and <stddef.h> or need NULL. */
#undef __need_NULL

When I looked at that section to confirm my memory I took for granted
that my files were getting compiled in C++ mode, not in __GNUG__ mode,
whatever that means!
The C and C++ standards are actually fairly close in this
respect: the macro NULL must be defined as something specifying
a null pointer constant. And a null pointer constant is an
integral constant expression evaluating to 0; C also allows the
null pointer constant to be such an expression explicitly
converted to void*, but that's an innovation of the
C standard---in traditional C, and on most platforms I've seen,
NULL has been #define'd to 0 in C. (Of course, it can be
#define'd to anything that is a null pointer constant: "(1-1)",
"'\0'", "0L"... or even something like "__null", provided the
compiler ensures that __null is treated as a null pointer
constant.)


I'd be surprised by that. The reason ((void*)0) is not allowed
as a null pointer constant in C++ is because unlike in C,
a void* doesn't implicitly to any other pointer type. (It's not
really a valid reason, since int's require compiler magic to
work as well; that compiler magic could have been extended to
((void*)0) as well.)

An excerpt from page 7 of:
http://www2.research.att.com/~bs/sibling_rivalry.pdf

"[...] C89’s definition of v o i d * allows a definition of the null
pointer that can’t be assigned to an i n t . I believe this to be the
only point where C is more strongly typed than C++."

I misrepresented his words (he wrote "more strongly typed" whereas I
recalled "stricter type checking system") but that should make no
difference.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top