3
votes

I am reposting a comp.std.c++ Usenet discussion here because that group has become very unreliable. The last few posts I've submitted there have gone into the void, and activity has all but ceased. I doubt I've been banned and/or everyone else just lost interest. Hopefully all interested people will find this discussion, and there will be a general migration. Maybe then they will appoint a new moderator.


Hello!

With my current interpretation of draft N3126 w.r.t. the conditional operator and xvalues, I expect the following assertions to hold:

 int i = 0;
 int& j = true? i : i;
 int&& k = true? std::move(i) : std::move(i);   // #2
 assert(&i == &j); // Holds since C++98
 assert(&i == &k); // Should this hold as well?

5.16/4 says:

If the second and third operands [to the conditional operator] are glvalues of the same value category and have the same type, the result is of that type and value category [...]

Though, it doesn't clearly say that the resulting glvalue refers to one of the objects the glvalue operands referred to -- or is this implied because otherwise it would return a prvalue? Using GCC 4.5.1 in C++0x mode the second assertion fails. The reference k seems to refer to some temporary object. Can somebody clarify whether the comiler is allowed to create such a temporary in case both operands around the colon are xvalues of the same type?

I'm currently assuming GCC is buggy and/or not up-to-date with respect to xvalues.

The followup question is: Wouldn't it be nice to be able to detect the value category of an expression? If we ignore the conditional operator we can detect the value category of an expression with decltype. But what is

 bool xvalue = std::is_rvalue_reference<
   decltype( true ? std::move(i) : std::move(i) ) >::value;

supposed to yield? Using GCC 4.5.1, the xvalue variable is initialized with false. Is this conforming to the current standard draft?

TIA, Sebastian

1
I think you mean [comp.std.c++], as implied by your link. Yes it does have some lag time but I think you may have just encountered a recent Google blackout. Did you post via Google Groups?Cheers and hth. - Alf
@Alf: I do post by Google Groups, but wouldn't that affect all groups? There is virtually no activity at comp.std.c++ since September, not so for the unmoderated groups.Potatoswatter
There are supposedly five moderators. Have you tried contacting them ([email protected])?James McNellis
You can also e-mail Pete Becker ([email protected]) with typographical and editorial errors (like a spelling error). The whole defect reporting process is too confusing, IMO. It'd be nice if the committee had Bugzilla or Trac or something that made it easy to report issues (of course, they'd probably say the correct way to submit defects is to join the committee, but the $1,200/year fee is a bit steep for that privilege).James McNellis
@MSalters: I meant that half-jokingly; every time I've interacted with committee members they have been very helpful. Anyway, in general, if someone wanted to formally participate, they'd have to join; for those in the US, the fee for joining INCITS J16 is $1,200/year. I know that if I wanted to and had the time to participate, I could probably do so through my employer, but many people don't have that option. Of course, having a high barrier to entry probably keeps the noise level down, which is usually a good thing.James McNellis

1 Answers

2
votes

I think GCC 4.5.1 is nonconforming wrt §5.16/4. Have you filed a bug report?

Anyway, I think it is conforming with that ternary operator code. decltype is defined by §7.1.6.2/4:

The type denoted by decltype(e) is defined as follows:

  • if e is an unparenthesized id-expression or a class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
  • otherwise, if e is a function call (5.2.2) or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function;
  • otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
  • otherwise, decltype(e) is the type of e. The operand of the decltype specifier is an unevaluated operand (Clause 5).

decltype works by fetching the appropriate declaration and returning the desired type from it. It has little intelligence with respect to non-overloaded operators. Perhaps another point

  • otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e

would be in order, particularly since, as written, xvalues get treated as prvalues. Furthermore, your expression corresponds exactly to the definition of std::common_type (§20.7.6.6/3).

One straightforward workaround (to coin a phrase :vP ):

template< typename T1, typename T2 >
struct common_type_and_category {
    typedef typename std::conditional<
        std::is_same< T1, T2 >::value,
        T1,
        typename std::common_type< T1, T2 >::type
    >::type type;
};