Adding logical implication to boost

Hi everyone, there has been a recent proposal to add logical implication to C++ as an operator. github tracking issue https://github.com/cplusplus/papers/issues/1641 P2971R2 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2971r2.pdf For a video description you can see this talk https://youtu.be/bgyY3x8y4PE?feature=shared&t=1470 by Walter(it is only few minutes, not entire talk). While I agree with concerns mentioned on the issue, i.e. using a *precious *token => on rarely used functionality I do think that implementing a simple function helper is reasonable. Poll in issue shows that this is also likely standardization future. POLL: We agree with adding a function object logical_implication (tentative name, akin logical_and, `logical_or’). SF F N A SA 9 12 3 0 0 As for if it is worthwhile to add this simple logic to boost instead of people just writing their own I will just say I would prefer to have something named in boost instead of people reinventing same thing many times in their projects. I have used it few times in my career, so quite rarely, but again that means I have used it much more often than 80+% of algorithms in <algorithm> header. As for location I presume best place would be Boost.Algorithm although you could say that Boost.Core can be a candidate because it is a basic operation and would benefit from shorter namespace. I would be still inclined against this since I have seen core/util/common become huge in many codebases I have worked in. I have tried to check if this already exists in Boost; all I found was an example in Boost.Hana.

While I haven’t been up to date with recent proposals, I share the same
concerns about using a precious token for such a small issue. In my work,
whenever I’ve had to do logical implications, I always naturally used ‘!a
|| b’, not once has the thought of “geez, wish C++ had => for logical
implication” crossed my mind.
In addition, I believe an ‘=>’ token would do better as a part of pattern
matching in the future (again, I haven’t really been up to date with recent
proposals, so I’m not aware of any work on pattern matching), although the
boost mailing list is not the best place to vent about this.
Regarding the location for a logical_implication<> function, I’d advocate
for either Boost.Algorithm or Boost.Functional, given that the
std::logical_XXX<> class templates are placed in the <functional> header;
even if it would be a mouthful to say and type, I don’t expect it to be
seen very often.
On Sat, 4 Jan 2025 at 21:43, Ivan Matek via Boost
Hi everyone,
there has been a recent proposal to add logical implication to C++ as an operator. github tracking issue https://github.com/cplusplus/papers/issues/1641 P2971R2 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2971r2.pdf
For a video description you can see this talk https://youtu.be/bgyY3x8y4PE?feature=shared&t=1470 by Walter(it is only few minutes, not entire talk).
While I agree with concerns mentioned on the issue, i.e. using a *precious *token => on rarely used functionality I do think that implementing a simple function helper is reasonable.
Poll in issue shows that this is also likely standardization future. POLL: We agree with adding a function object logical_implication (tentative name, akin logical_and, `logical_or’).
SF F N A SA 9 12 3 0 0
As for if it is worthwhile to add this simple logic to boost instead of people just writing their own I will just say I would prefer to have something named in boost instead of people reinventing same thing many times in their projects. I have used it few times in my career, so quite rarely, but again that means I have used it much more often than 80+% of algorithms in <algorithm> header.
As for location I presume best place would be Boost.Algorithm although you could say that Boost.Core can be a candidate because it is a basic operation and would benefit from shorter namespace. I would be still inclined against this since I have seen core/util/common become huge in many codebases I have worked in.
I have tried to check if this already exists in Boost; all I found was an example in Boost.Hana.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Sun, Jan 5, 2025 at 3:27 PM Traian Enache
In my work, whenever I’ve had to do logical implications, I always naturally used ‘!a || b’, not once has the thought of “geez, wish C++ had => for logical implication” crossed my mind.
As I said I agree with regards to =>. In regards to boost::implies vs !a || b my belief is that it heavily depends on the person. For me (and I presume many others even if we are not majority) even after many years of programming if I saw something like boost::implies(student.graduaded(), student.num_active_courses() == 0) reads much much nicer than !student.graduaded() || student.num_active_courses() == 0 So I am not trying to covert anybody to prefer implies function call, but I feel there is large number of people that would prefer a helper. As mentioned in the paper there is also the thing with the short circuit evaluation if second argument is invocable returning bool. P.S. if you do not mind sharing details about your usecases I wonder when did you find use for implication?.
Regarding the location for a logical_implication<> function, I’d advocate for either Boost.Algorithm or Boost.Functional, given that the std::logical_XXX<> class templates are placed in the <functional> header; even if it would be a mouthful to say and type, I don’t expect it to be seen very often.
Regarding <functional> header I do not think it fits there primarily, although I can imagine that is where std::logical_implication will be added in C++. For me they are there and exist because in C++ we can not pass operators to algorithms, e.g. std::accumulate(a.begin(), a.end(), 1, *), but this seems like a generic helper function because unlike && and || we have no operator for it. So I think it may be useful to add it in a way that enables one to pass it around(although I never had need to do this) but primary use is to just immediately invoke it yourself. I may be missing something, but this is my current thinking. On Mon, Jan 6, 2025 at 12:43 PM Richard Hodges via Boost < boost@lists.boost.org> wrote:
C++ standardisation seems to have jumped the shark.
I was just mentioning the proposal for context, so not sure this is super related to helper function, but I do not think this will get standardized, for example Walter in 2013 had swap operator :=: proposal.

pon., 6 sty 2025 o 19:43 Ivan Matek via Boost
On Sun, Jan 5, 2025 at 3:27 PM Traian Enache
wrote: In my work, whenever I’ve had to do logical implications, I always naturally used ‘!a || b’, not once has the thought of “geez, wish C++ had => for logical implication” crossed my mind.
As I said I agree with regards to =>. In regards to boost::implies vs !a || b my belief is that it heavily depends on the person. For me (and I presume many others even if we are not majority) even after many years of programming if I saw something like boost::implies(student.graduaded(), student.num_active_courses() == 0) reads much much nicer than !student.graduaded() || student.num_active_courses() == 0
So I am not trying to covert anybody to prefer implies function call, but I feel there is large number of people that would prefer a helper. As mentioned in the paper there is also the thing with the short circuit evaluation if second argument is invocable returning bool.
If you are only interested in a convenience function (and not the short-circuiting properties), this reminds me of Peter Dimov's remark about operator =>: It already exists in C++ and is spelled operator <=. Regards, &rzej;
P.S. if you do not mind sharing details about your usecases I wonder when did you find use for implication?.
Regarding the location for a logical_implication<> function, I’d advocate for either Boost.Algorithm or Boost.Functional, given that the std::logical_XXX<> class templates are placed in the <functional> header; even if it would be a mouthful to say and type, I don’t expect it to be seen very often.
Regarding <functional> header I do not think it fits there primarily, although I can imagine that is where std::logical_implication will be added in C++. For me they are there and exist because in C++ we can not pass operators to algorithms, e.g. std::accumulate(a.begin(), a.end(), 1, *), but this seems like a generic helper function because unlike && and || we have no operator for it. So I think it may be useful to add it in a way that enables one to pass it around(although I never had need to do this) but primary use is to just immediately invoke it yourself. I may be missing something, but this is my current thinking.
On Mon, Jan 6, 2025 at 12:43 PM Richard Hodges via Boost < boost@lists.boost.org> wrote:
C++ standardisation seems to have jumped the shark.
I was just mentioning the proposal for context, so not sure this is super related to helper function, but I do not think this will get standardized, for example Walter in 2013 had swap operator :=: proposal.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Tue, Jan 7, 2025 at 2:07 AM Andrzej Krzemienski
pon., 6 sty 2025 o 19:43 Ivan Matek via Boost
napisał(a): If you are only interested in a convenience function (and not the short-circuiting properties), this reminds me of Peter Dimov's remark about operator =>: It already exists in C++ and is spelled operator <=.
It is interesting trick, but again I *personally* prefer the named function. Also all this discussions about asserts made me think that maybe it would be nice to have BOOST_STATIC_IMPLIES. This is just my intuition, I do not know how many people would actually use it, and how common are implications in static_assert.

On 06.01.25 19:43, Ivan Matek via Boost wrote:
As I said I agree with regards to =>. In regards to boost::implies vs !a || b my belief is that it heavily depends on the person. For me (and I presume many others even if we are not majority) even after many years of programming if I saw something like boost::implies(student.graduaded(), student.num_active_courses() == 0) reads much much nicer than !student.graduaded() || student.num_active_courses() == 0
The problem here is that your example is closer to the English usage of the word "implies" than to the usage in boolean logic that we are talking about. "A implies B" in English usually means that there is a logical connection such that B is necessarily true if A is true. For example, a student who has graduated necessarily has no active courses. "A => B" merely means that either A is false or B is true. For example, "I am the president of the United States => there is world peace" is trivially true because I am not the president of the United States, even though if I would almost certainly be unable to achieve world peace even if I were the president of the United States. The C++ expression "!A || B" is actually closer to the correct English than "A => B" for expressing this condition. -- Rainer Deyke - rainerd@eldwood.com

Am 07.01.25 um 16:16 schrieb Rainer Deyke via Boost:
On 06.01.25 19:43, Ivan Matek via Boost wrote:
boost::implies(student.graduaded(), student.num_active_courses() == 0) reads much much nicer than !student.graduaded() || student.num_active_courses() == 0
The problem here is that your example is closer to the English usage of the word "implies" than to the usage in boolean logic that we are talking about. "A implies B" in English usually means that there is a logical connection such that B is necessarily true if A is true. For example, a student who has graduated necessarily has no active courses.
"A => B" merely means that either A is false or B is true. For example, "I am the president of the United States => there is world peace" is trivially true because I am not the president of the United States, even though if I would almost certainly be unable to achieve world peace even if I were the president of the United States. The C++ expression "!A || B" is actually closer to the correct English than "A => B" for expressing this condition. Isn't that is exactly what was written above? I.e. `A => B` == `boost::implies(A, B)` == `!A || B`
Or with the example: if( boost::implies(student.graduaded(), student.num_active_courses() == 0) ) /*...*/;` In plain English: "If a graduated student implies he has no active courses" So I don't see how "!A || B" is closer to anything than "A => B" if they are the same thing. What am I missing here? Or did you mistype anything? Aside from that I don't actually see how that could be useful outside of asserts. I.e. `assert ( implies(this, that) )` makes sense and is readable. But `if implies(this, that)` not so much. Because it sounds much more general than it is it might be rather confusing. With your example `if( i_am_president() "implies" is_world_peace() )` is likely true right now, but if I became president at some point someone trusting this statement would likely be disappointed. Not that such things ever stopped any politician ;-) It still boils down to the English language which doesn't match the logical interpretation which is likely what you intended to say because also when reading the code `student.graduaded()` might not magically ensure `num_active_courses() == 0` although it reads (in English terms) that way. TLDR: I wouldn't want such a function or even operator as I don't see any reasonable uses outside of assertions.

On Sat, 4 Jan 2025 at 20:43, Ivan Matek via Boost
Hi everyone,
there has been a recent proposal to add logical implication to C++ as an operator. github tracking issue https://github.com/cplusplus/papers/issues/1641 P2971R2 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2971r2.pdf
C++ standardisation seems to have jumped the shark.
For a video description you can see this talk https://youtu.be/bgyY3x8y4PE?feature=shared&t=1470 by Walter(it is only few minutes, not entire talk).
While I agree with concerns mentioned on the issue, i.e. using a *precious *token => on rarely used functionality I do think that implementing a simple function helper is reasonable.
Poll in issue shows that this is also likely standardization future. POLL: We agree with adding a function object logical_implication (tentative name, akin logical_and, `logical_or’).
SF F N A SA 9 12 3 0 0
As for if it is worthwhile to add this simple logic to boost instead of people just writing their own I will just say I would prefer to have something named in boost instead of people reinventing same thing many times in their projects. I have used it few times in my career, so quite rarely, but again that means I have used it much more often than 80+% of algorithms in <algorithm> header.
As for location I presume best place would be Boost.Algorithm although you could say that Boost.Core can be a candidate because it is a basic operation and would benefit from shorter namespace. I would be still inclined against this since I have seen core/util/common become huge in many codebases I have worked in.
I have tried to check if this already exists in Boost; all I found was an example in Boost.Hana.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (6)
-
Alexander Grund
-
Andrzej Krzemienski
-
Ivan Matek
-
Rainer Deyke
-
Richard Hodges
-
Traian Enache