switch( i ) {
case (3,2): std::cout << "i is two\n";
}
template< typename t >
auto fn( t o )
-> typename std::enable_if< ( std::declval< t >() * std::declval< t >(), true ) >::type
{ std::cout << o * o << '\n'; }
template< typename t >
auto fn( t o )
-> typename std::enable_if< ( o * o, true ) >::type // Error (SFINAE?)
{ std::cout << o * o << '\n'; }
C++98 forbade the comma operator in a constant-expression context. C++11 makes a constant-expression a grammatical conditional-expression, which excludes the comma at the top level but allows it inside parentheses.
switch( i ) {
case (3,2): std::cout << "i is two\n";
}
It's fairly useless, but can be used for SFINAE where even discarded expressions are significant.
template< typename t >
auto fn( t o )
-> typename std::enable_if< ( std::declval< t >() * std::declval< t >(), true ) >::type
{ std::cout << o * o << '\n'; }
Note that declval or void must be used because the expression is evaluated, although nothing could potentially come of it.
template< typename t >
auto fn( t o )
-> typename std::enable_if< ( o * o, true ) >::type // Error (SFINAE?)
{ std::cout << o * o << '\n'; }
There doesn't seem to be implementation consensus.
Clang accepts all such examples but GCC complains that the expression is "used," even if protected by a cast to void or decltype.
SFINAE is not applied so any call to the overload set stops compilation. (Previous versions of GCC ignored the LHS of the comma under SFINAE, as well as unevaluated RHS of && and ||.)
On 22 Sep 2013 06:02, "David Krauss" <pot...@gmail.com> wrote:
>
> On 9/22/13 4:05 PM, Richard Smith wrote:
>>
>> This use of comma should not be recommended for fully generic code: it can
>> fail if operator, is overloaded
>
> Oh, good point. That's a corner case to be sure, but an ideal idiom couldn't be tripped up like that.
>
>> , and the search for an overloaded operator,
>> requires the LHS to be a complete type, which can sometimes be undesirable.
>> Plus this doesn't work because it odr-uses std::declval<t> (also, a call to
>> declval can't be an evaluated subexpression of a constant expression).
>>
>> Note that declval or void must be used because the expression is evaluated,
>> although nothing could potentially come of it.
>
> Yeah. Sorry, if I'd posted my previous message sooner, you wouldn't have had to write all that :( .
>
>>>
>>> template< typename t >
>>> auto fn( t o )
>>> -> typename std::enable_if< ( o * o, true ) >::type // Error (SFINAE?)
>>> { std::cout << o * o << '\n'; }
>>>
>>> There doesn't seem to be implementation consensus.
>>>
>> This SFINAE check doesn't do what you seemed to want here; you need a
>> pretty exotic type for this function to ever work. Something like:
>>
>> struct S {}; constexpr bool operator*(S&, S&) { return true; }
>
> constexpr doesn't help because the argument to operator* is already a parameter from fn.
That's not a problem, per the rules in [expr.const]p2. Clang accepts fn<S>…
> I don't think it ever could work, and therefore such a template cannot ever produce a valid instantiation, which is ill-formed with no diagnostic required (a.k.a. undefined behavior).
>
> Otherwise it confusingly "works half the time," i.e. when the function isn't supposed to be selected, and on half the platforms, i.e. Clang and others that fail to diagnose the uninstantiable template.
>
> This story all began when someone (an occasional participant here) suggested to me the (expr, true) "idiom," claiming it worked for him. I tried it out in my project, noticed it "worked" in Clang but not GCC, and shelved it without noticing its defectiveness until now, after the first post of this thread.
>
> Such deceptive defectiveness is probably justification enough for outlawing it entirely. I'm now thinking there should be a rule forbidding the comma added back to 5.19, although an overloaded comma should be allowed.
>
>> GCC (and EDG) reject this when they see the template definition, so SFINAE is not relevant.
>
> I hadn't run enough experiments to notice that. But it's not a bug; they actually have higher QOI in rejecting a template that could never succeed.
>
>
> --
>
> --- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
> To post to this group, send email to std-dis...@isocpp.org.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
I disagree with your argument and your conclusion. In C++11, the comma operator is useful within constexpr functions, because we aren't allowed multiple statements: template<typename T> constexpr T my_array<T>::at(size_type n) { return (n < size() || throw "n too large"), (*this)[n]; }
In C++14, it's useful in essentially all of the cases where it's useful outside of constant expressions: constexpr void do_stuff(int x[]) { for (int i = 0, j = 100; i != j; ++i, --j) x[i] = x[j]; }
More philosophically, we shouldn't ban things from constant expressions simply because we're not imaginative enough to find the cases where they're genuinely useful. Constant expressions should not be a semi-random sublanguage of C++, missing random features, to the extent that we can avoid that.
These days, top-level commas are prohibited mostly because constant-expressions tend to occur in contexts where a comma would mean something else.
David Krauss <pot...@gmail.com> writes:
| On 9/22/13 9:11 PM, Gabriel Dos Reis wrote:
| > David Krauss <pot...@gmail.com> writes:
| >
| > [...]
| >
| > | Such deceptive defectiveness is probably justification enough for
| > | outlawing it entirely. I'm now thinking there should be a rule
| > | forbidding the comma added back to 5.19, although an overloaded comma
| > | should be allowed.
| >
| > I don't understand that reasoning.
| In C++03 [expr.const] disallowed the comma. C++11 has allowed it, but
| it seemingly can't do anything useful unless it is overloaded.
For C++11 I proposed to allow it because the restriction appeared
arbitrary and all reasons I've heard as rationale for its ban appear
very unconvincing and specious to me.
| One obvious use for the comma is enable_if< ( expr, true )>, but this
| produces UB. I haven't seen any other potential use.
I do not understand that statement about UB.
| Since this new feature was recently added by omission and can only do
| harm, it should probably be removed.
What makes you believe it was added by omission?