[libcxx-commits] [PATCH] D136318: [libc++] type_traits: fix short-circuiting in std::conjunction.

Aaron Jacobs via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 20 16:20:58 PDT 2022


jacobsa added a comment.

Thanks! I don't have commit access, so it would be great if you could do it.
Please credit:

  Aaron Jacobs <jacobsa at google.com>



================
Comment at: libcxx/include/__type_traits/conjunction.h:26-28
-struct __conjunction_impl {
-  using type = conditional_t<!bool(_Arg::value), _Arg, typename __conjunction_impl<_Args...>::type>;
-};
----------------
ldionne wrote:
> jacobsa wrote:
> > philnik wrote:
> > > ldionne wrote:
> > > > jacobsa wrote:
> > > > > ldionne wrote:
> > > > > > I think this would be an equivalent fix, no?
> > > > > Perhaps, but is there any reason to prefer that? I don't see any benefit to the
> > > > > two-level implementation; it just makes it harder to understand as far as I can
> > > > > tell. Am I missing something?
> > > > I believe the goal might have been to avoid partially specializing `std::conjunction` itself as a matter of conformance. @philnik is that something you had in mind? If so, we'd need a test for that too (which @philnik can help you with since he should have added it when he last modified these traits :-) ).
> > > > 
> > > > If that's not a concern, then either implementation should do.
> > > I don't think that's a problem; I definitely didn't have it in mind then. I also can't remember why I implemented it in this way, most likely because I replaced `_And` and didn't think of just specializing `conjunction` itself.
> > It seems like [meta.logical]/3 specifically says it *will* be a specialization,
> > if I read the wording correctly:
> > 
> >     https://timsong-cpp.github.io/cppwp/n4868/meta.logical#3
> > 
> > > For a specialization `conjunction<B1, …, BN>`, if there is a ...
> > 
> > That said, is there even any way to differentiate the two from outside?
> My thinking was along the lines of "what if a user specializes it, would it behave correctly"? That's extremely pedantic and I'm fine with your approach.
> 
> Thanks both for the explanation, I've been stretched for time to research myself.
Ah I see, thanks. Programs that specialize std::conjunction are forbidden [according to cppreference](https://en.cppreference.com/w/cpp/language/extending_std):

> It is allowed to add template specializations for any standard library class template to the namespace `std` only if the declaration depends on at least one program-defined type [...]
>
> [..]
>
> * None of the templates defined in `<type_traits>` may be specialized for a program-defined type, except for `std::common_type` and `std::basic_common_reference`. This includes the type traits and the class template std::integral_constant.

I believe this comes from [meta.rqmts/4](https://timsong-cpp.github.io/cppwp/n4868/meta#rqmts-4) in C++20:

> Unless otherwise specified, the behavior of a program that adds specializations for any of the templates specified in [meta] is undefined.


================
Comment at: libcxx/test/std/utilities/meta/meta.logical/conjunction.compile.pass.cpp:23
 struct False { static constexpr bool value = false; };
 
 struct MySpecialTrueType { static constexpr auto value = true; static constexpr auto MySpecial = 23; };
----------------
philnik wrote:
> ldionne wrote:
> > jacobsa wrote:
> > > ldionne wrote:
> > > > Do we have the same issue for `disjunction`? Regardless, IMO we should add a test.
> > > I added the corresponding tests there for symmetry. They do pass, although I'm
> > > not confident there isn't a similar bug because its implementation is a little
> > > weird. If you would take it, I'd be happy to send a follow-up commit to make
> > > its implementation straightforward pattern matching like this one.
> > That may make sense, but let's first hear what @philnik has to say about the implementation of conjunction.
> The `disjunction` implementation is a bit weird to avoid instantiating lots of classes. Unless you can show that the optimization doesn't actually do anything, I'd rather keep it as-is.
Ack, thanks.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136318/new/

https://reviews.llvm.org/D136318



More information about the libcxx-commits mailing list