Issue 2587: "Convertible to bool" requirement in conjunction and disjunction (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.
2587. "Convertible to bool" requirement in conjunction and disjunction
Section: 21.3.10 [meta.logical] Status: C++17 Submitter: Tim Song Opened: 2016-01-18 Last modified: 2017-12-05
Priority: 3
View all other issues in [meta.logical].
View all issues with C++17 status.
Discussion:
The specification of conjunction and disjunction in 21.3.10 [meta.logical] p2 and p5 requires Bi::value to be convertible to bool, but nothing in the specification of the actual behavior of the templates, which instead uses the expressions Bi::value == false and Bi::value != false instead, actually requires this conversion.
If the intention of this requirement is to allow implementations to pass Bi::value directly to std::conditional, like the sample implementation in P0013R1:
template<class B1, class B2> struct and_<B1, B2> : conditional_t<B1::value, B2, B1> { };
then it's insufficient in at least two ways:
- Nothing in the specification requires the result of comparing
Bi::valuewithfalseto be consistent with the result of the implicit conversion. This is similar to LWG [2114](lwg-defects.html#2114 "Incorrect "contextually convertible to bool" requirements (Status: Resolved)")(i), though I don't think theBooleanTestablerequirements in that issue's P/R coversBi::value == falseandBi::value != false. - More importantly, the above implementation is ill-formed for, e.g.,
std::conjunction<std::integral_constant<int, 2>, std::integral_constant<int, 4>>, because converting 2 toboolis a narrowing conversion that is not allowed for non-type template arguments (see 7.7 [expr.const]/4). (Note that GCC currently doesn't diagnose this error at all, and Clang doesn't diagnose it inside system headers.) It's not clear whether such constructs are intended to be supported, but if they are not, the current wording doesn't prohibit it.
[2016-08-03 Chicago LWG]
Walter, Nevin, and Jason provide initial Proposed Resolution.
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
- Change 21.3.10 [meta.logical] as indicated:
template<class... B> struct conjunction : see below { };
[…]
-3- The BaseCharacteristic of a specialization
conjunction<B_1_, ..., B_N_>is the first typeB_i_in the listtrue_type, B_1_, ..., B_N_for which~~B_i_::value == false~~! bool(B_i_::value), or if every~~B_i_::value != false~~bool(B_i_::value), the BaseCharacteristic is the last type in the list. […]-4- For a specialization
conjunction<B1, ..., B_N_>, if there is a template type argumentB_i_with~~B_i_::value == false~~! bool(B_i_::value), then instantiating […]template<class... B> struct disjunction : see below { };
[…]
-6- The BaseCharacteristic of a specialization
disjunction<B_1_, ..., B_N_>is the first typeB_i_in the listfalse_type, B_1_, ..., B_N_for which~~B_i_::value != false~~bool(B_i_::value), or if every~~B_i_::value == false~~! bool(B_i_::value), the BaseCharacteristic is the last type in the list. […]-7- For a specialization
disjunction<B1, ..., BN>, if there is a template type argumentBiwith~~B_i_::value != false~~bool(B_i_::value), then instantiating […]template struct negation : bool_constant<!bool(B::value)> { };
-8- The class template negation forms the logical negation of its template type argument. The type
negation<B>is a UnaryTypeTrait with a BaseCharacteristic ofbool_constant<!bool(B::value)>.
[Dec 2017 - The resolution for this issue shipped in the C++17 standard; setting status to 'C++17']
Proposed resolution:
The resolution for this issue was combined with the resolution for LWG 2567(i), so 2567(i)resolves this issue here as well.