views:

605

answers:

4

To value initialize an object of type T, one would do something along the lines of one of the following:

T x = T();
T x((T()));

My question concerns types specified by a combination of simple type specifiers, e.g., unsigned int:

unsigned int x = unsigned int();
unsigned int x((unsigned int()));

Visual C++ 2008 and Intel C++ Compiler 11.1 accept both of these without warnings; Comeau 4.3.10.1b2 and g++ 3.4.5 (which is, admittedly, not particularly recent) do not.

According to the C++ standard (C++03 5.2.3/2, expr.type.conv):

The expression T(), where T is a simple-type-specifier (7.1.5.2) for a non-array complete object type or the (possibly cv-qualified) void type, creates an rvalue of the specified type, which is value-initialized

7.1.5.2 says, "the simple type specifiers are," and follows with a list that includes unsigned and int.

Therefore, given that in 5.2.3/2, "simple-type-specifier" is singular, and unsigned and int are two type specifiers, are the examples above that use unsigned int invalid? (and, if so, the followup is, is it incorrect for Microsoft and Intel to support said expressions?)

This question is more out of curiosity than anything else; for all of the types specified by a combination of multiple simple type specifiers, value initialization is equivalent to zero initialization. (This question was prompted by comments in response to this answer to a question about initialization).

+1  A: 

Hmm, sometimes you need a typedef. If it doesn't say a diagnostic is required, then it's not incorrect for them to support this. Nevertheless, for portability, you can use a typedef (uint16_t or uint64_t, although those might not be right), or quote the typename with a template:

iterator<void, unsigned long>::value_type( 5 )

How's that for unreasonably verbose?

Edit: Duh, or simply 5ul. That leaves unsigned short, unsigned char, and signed char as the only types you can't easily explicitly construct.

Potatoswatter
I'd rather have: `template <typename T> struct same_type{ typedef T type; };`, little easier.
GMan
I'd rather have neither ;v) . I just tried to think of something in the STL. The omission of an identity template and an identity functor always baffled me.
Potatoswatter
You are right about the correctness issue. "A conforming implementation may have extensions...provided they do not alter the behavior of any well-formed program" (1.4/8, intro.compliance); I had forgotten exactly what the rules were concerning the language grammar, extensions, and compliance.
James McNellis
A `std::identity` is present in the latest C++0x draft (cf. n3000, 20.3.3/1).
James McNellis
Ah, `identity`. I knew there was a more concise way of saying `same_type`.
GMan
As for any practical issue, there really isn't one. I meant the question purely as an inquiry as to whether it was allowed by the standard.
James McNellis
Let's praise `std::identity`: http://stackoverflow.com/questions/75538/hidden-features-of-c/1414869#1414869 :) It's got so many nice use cases :)
Johannes Schaub - litb
+1  A: 

In §7.1.5.2, keep reading down to table 7, which has the full list of what's allowed as a simple specifier (which does include "unsigned int").

Jerry Coffin
I'd say the the table is not intended to define the notion of "simple type specifier". Moreover, the wording after the table mentions "multiple simple type specifiers". This is the wording that allows us to use `unsigned int` and `int unsigned` interchangeably, which probably means that `unsigned int` is in fact *multiple* simple type specifiers.
AndreyT
@AndreyT: That was my interpretation as well. I also think the header of the table column, "Specifier(s)" implies as much.
James McNellis
Hmm...in my copy of the standard, the title of the table is "Simple type specifiers and the types they specify." With that title, it seems like an awful stretch to believe that something in the table is *not* a simple type specifier.
Jerry Coffin
I don't think that title excludes the interpretation that the column "Specifier(s)" contains combinations of simple type specifiers, especially in light of the grammar description in §7.1.5.2/1 and the list in §7.1.5/1. I've been wrong before, though. (On a totally unrelated note, is there an easy way to put the § character into answers and comments?)
James McNellis
@James McNelis: I don't think it completely excludes the interpretation, but I do think it makes it a stretch. Entering §: under Windows, you press Alt then enter the decimal code with a leading zero (0167) using the numeric keypad. Under Linux you hold the Alt and Ctrl keys while typing in the hex value (A7). If you do it a lot, X supports an ~/.Xmodmap file, and Windows has a keyboard layout creator. For other systems, you'll probably have to do some Googling...
Jerry Coffin
A: 

7.1.5.2:

The simple-type-specifiers specify either a previously-declared user-defined type or one of the fundamental types`

This implies that unsigned int i = unsigned int() is legal, since unsigned int is a fundamental type (and thus a simple-type-specifier, see 3.9.1).

same applies for types like:

long double
long long
long long int
unsigned long
unsigned long long int
short int
...
smerlin
I think there is a logical fallacy here: your argument is that, "If T is a simple type specifier, then T is either a previously defined user defined type or T is one of the fundamental types. T is a fundamental type, therefore T is a simple type specifier" (you are affirming the consequent).
James McNellis
@James: I dont understand what you are saying, your question stated that `T t = T()` is legal for simple-type-specifiers, and my quote says that fundamental types ARE simple-type specifiers, so `unsigned int i = unsigned int()` is legal.
smerlin
I apologize; I clearly hadn't had enough coffee yet when I posted that this morning. I disagree with your interpretation that if `T` is a fundamental type, `T` must also a simple type specifier. I believe that `T` may in fact be multiple simple type specifiers (e.g. `unsigned int` is a fundamental type but is designated by two simple type specifiers, `unsigned` and `int`). I think there are a lot of statements to support this, e.g. 3.9.1, note 40: "See 7.1.5.2 regarding the correspondence between types and the _sequences_ of type-specifiers that designate them" (emphasis mine)
James McNellis
+4  A: 

I posted this question to comp.lang.c++.moderated.

Daniel Krügler of the C++ standards committee agreed with the interpretation that unsigned int is a combination of simple type specifiers, and is not itself a simple type specifier.

Concerning the caption of table 7 referenced by Jerry Coffin, Krügler says:

I agree that the header of Table 7 (which is Table 9 in the most recent draft N3000) is somewhat misleading, but the preceeding text in [dcl.type.simple]/2 looks very clear to me, when it says:

Table 7 summarizes the valid combinations of simple-type-specifiers and the types they specify."

(I apologize it took me so long to post this back here from the newsgroup; it completely slipped my mind)

James McNellis