Discussion:
[std-proposals] Proposal Ternary Right Fold Expression
f***@gmx.de
2018-01-20 11:20:55 UTC
Permalink
C++17 offers fold expressions for binary operators.

I want to make a proposal to add a right fold expression for the ternary
operator ?:

( C ? E : ... : I )

should expand to ( C(1) ? E(1) : ( ... ( C(N-1) ? E(N-1) : ( C(N) ? E(N) :
I ) ) ) )


and


( C ? E : ... )
should expand to

( C(1) ? E(1) : ( ... ( C(N-2) ? E(N-2) : ( C(N-1) ? E(N-1) : E(N) ) ) )


The full proposal with motivating examples can be found on
https://github.com/zingsheim/ProposalTernaryFold/blob/master/ProposalTernaryFold.md

Note: A initial idea of this proposal has already been publish on reddit
<https://www.reddit.com/r/cpp/comments/7qcgne/rfc_proposal_ternary_fold_expression/>
.

Comments on this initial version of the proposal are welcome.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/95b46782-075f-4e96-8c1f-6b4757a4d049%40isocpp.org.
m***@gmail.com
2018-01-20 12:52:29 UTC
Permalink
Are there any uses besides search in a parameter pack?

Because I believe there should be a cleaner way to represent that.

I believe something like this was proposed

for...(const auto i : js)
{
if(i == j)
return f<i>();
}

You can test if j is out of bounds even today if(j >= sizeof...(js)) throw


There is no established practice of ternary operator to do search among
values, hence using it that way is no less confusing then recursion.

I don't say I am against the proposal! Just that one example should be
handled better.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/67153695-17bb-4c77-805b-4e36efc5ace6%40isocpp.org.
f***@gmx.de
2018-01-20 15:15:38 UTC
Permalink
Post by m***@gmail.com
Are there any uses besides search in a parameter pack?
Because I believe there should be a cleaner way to represent that.
I believe something like this was proposed
for...(const auto i : js)
{
if(i == j)
return f<i>();
}
You can test if j is out of bounds even today if(j >= sizeof...(js)) throw
There is no established practice of ternary operator to do search among
values, hence using it that way is no less confusing then recursion.
I don't say I am against the proposal! Just that one example should be
handled better.
1. There are no usages beside the selection of one out of many
alternatives. Since the ordinary ternary operator is a selection of one out
of two.
2. To your comparison with for... :
With the folded ternary expression it is possible to make use of the
result immediately, since you could write:

int ret = ( (j == js) ? f<js>() : ... );

3. To your remark: "There is no established practice of ternary operator
to do search among values"
See for example:

https://www.reddit.com/r/cpp/comments/2y7a20/secrets_of_the_conditional_ternary_operator/cpb8cwe/
and

http://twistedoakstudios.com/blog/Post5273_how-to-read-nested-ternary-operators
4. To your remark: "using it that way is no less confusing then
recursion"
I recently got the true remark that recursions are hard to debug. See
https://www.reddit.com/r/cpp/comments/7pya5s/stdvisit_overhead/dsnrbt2/.
(By the way this reddit entry was the reason to start thinking about
fold ternary expressions.)
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/29fb5ea3-4975-4793-97e0-5e5d9b2df4f7%40isocpp.org.
m***@gmail.com
2018-01-20 14:53:41 UTC
Permalink
Because we are speculating

template <std::size_t... js>
auto test_impl(std::size_t j, std::index_sequence<js...>)
{
switch(j)
{
case js: { return f<js>; break; } ... *//< expand to switch blocks*
default: break;
}
}

Or without the need of index_sequence

template <std::size_t n>
auto test(std::size_t j)
{
constexpr for(auto i; i < n; ++i ) *//< both i and n are constexpr*
{
if(i == j)
return f<i>();
}
}

The latter will be equivalent of:


template <std::size_t n>
auto test(std::size_t j)
{
{
constexpr int i = 0;

if(i == j)
return f<i>();
}

......

{
constexpr int i = n-1;

if(i == j)
return f<i>();
}
}

OR also equivalent to a switch statement - depending on how smart the
compiler is and what type of code there is in the for block
Post by f***@gmx.de
C++17 offers fold expressions for binary operators.
I want to make a proposal to add a right fold expression for the ternary
( C ? E : ... : I )
should expand to ( C(1) ? E(1) : ( ... ( C(N-1) ? E(N-1) : ( C(N) ? E(N)
: I ) ) ) )
and
( C ? E : ... )
should expand to
( C(1) ? E(1) : ( ... ( C(N-2) ? E(N-2) : ( C(N-1) ? E(N-1) : E(N) ) ) )
The full proposal with motivating examples can be found on
https://github.com/zingsheim/ProposalTernaryFold/blob/master/ProposalTernaryFold.md
Note: A initial idea of this proposal has already been publish on reddit
<https://www.reddit.com/r/cpp/comments/7qcgne/rfc_proposal_ternary_fold_expression/>
.
Comments on this initial version of the proposal are welcome.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f75cbe71-9f5c-43fe-898e-06318e301b6f%40isocpp.org.
m***@gmail.com
2018-01-20 14:55:18 UTC
Permalink
Because we are speculating:

template <std::size_t... js>
auto test_impl(std::size_t j, std::index_sequence<js...>)
{
switch(j)
{
case js: { return f<js>; break; } ... //< expand to switch blocks
default: break;
}
}

Or without the need of index_sequence

template <std::size_t n>
auto test(std::size_t j)
{
constexpr for(auto i; i < n; ++i ) //< i and n are constexpr
{
if(i == j)
return f<i>();
}
}

The latter will be equivalent of:

template <std::size_t n>
auto test(std::size_t j)
{
{
constexpr int i = 0;

if(i == j)
return f<i>();
}
......
{
constexpr int i = n-1;

if(i == j)
return f<i>();
}
}

OR also equivalent to a switch statement - depending on how smart the
compiler is and what type of code there is in the 'for' block
Post by f***@gmx.de
C++17 offers fold expressions for binary operators.
I want to make a proposal to add a right fold expression for the ternary
( C ? E : ... : I )
should expand to ( C(1) ? E(1) : ( ... ( C(N-1) ? E(N-1) : ( C(N) ? E(N)
: I ) ) ) )
and
( C ? E : ... )
should expand to
( C(1) ? E(1) : ( ... ( C(N-2) ? E(N-2) : ( C(N-1) ? E(N-1) : E(N) ) ) )
The full proposal with motivating examples can be found on
https://github.com/zingsheim/ProposalTernaryFold/blob/master/ProposalTernaryFold.md
Note: A initial idea of this proposal has already been publish on reddit
<https://www.reddit.com/r/cpp/comments/7qcgne/rfc_proposal_ternary_fold_expression/>
.
Comments on this initial version of the proposal are welcome.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/eff4cdc9-f673-4ad6-bc8c-d14859ca01ef%40isocpp.org.
Barry Revzin
2018-01-22 02:23:24 UTC
Permalink
Post by f***@gmx.de
C++17 offers fold expressions for binary operators.
I want to make a proposal to add a right fold expression for the ternary
( C ? E : ... : I )
should expand to ( C(1) ? E(1) : ( ... ( C(N-1) ? E(N-1) : ( C(N) ? E(N)
: I ) ) ) )
and
( C ? E : ... )
should expand to
( C(1) ? E(1) : ( ... ( C(N-2) ? E(N-2) : ( C(N-1) ? E(N-1) : E(N) ) ) )
The full proposal with motivating examples can be found on
https://github.com/zingsheim/ProposalTernaryFold/blob/master/ProposalTernaryFold.md
Note: A initial idea of this proposal has already been publish on reddit
<https://www.google.com/url?q=https%3A%2F%2Fwww.reddit.com%2Fr%2Fcpp%2Fcomments%2F7qcgne%2Frfc_proposal_ternary_fold_expression%2F&sa=D&sntz=1&usg=AFQjCNFAwhlqn2nq06q8ziJ2rUUJ4jksuA>
.
Comments on this initial version of the proposal are welcome.
For your first example, is this really better than
https://www.reddit.com/r/cpp/comments/7qcgne/rfc_proposal_ternary_fold_expression/dso41rx/?st=jcpl1gmq&sh=9ee1b9c4
?

For your second example, is this really better than having a hashtable from
std::string to std::function<std::string(std::string const&)> and just
doing a lookup + call?

Also, it's called the conditional operator, it's not called the ternary
operator (it simply is a ternary operator).
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/643bc18d-3118-40cc-8a4a-7b7c563ae54a%40isocpp.org.
Frank Zingsheim
2018-01-22 21:04:34 UTC
Permalink
Post by Barry Revzin
For your first example, is this really better than
https://www.reddit.com/r/cpp/comments/7qcgne/rfc_proposal_ternary_fold_expression/dso41rx/?st=jcpl1gmq&sh=9ee1b9c4
?
Clang can optimize the nested conditional operators at best.
Godbolt comparison conditional vs. function pointers (clang)
<https://gcc.godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAKxAEZSAbAQwDtRkBSAJgCFufSAZ1QBXYskwgA5NwDMeFsgYisAag6yAwskEF0WAGYbsHAAwBBM%2BYKYAtgAdmN9Vt3oQIQXgBemAPoEqnjGVm4eXr4BqgYQAJRWHADsfBaqaarEmARiLEEAVMGyKZaJACIJFmGePv6BNroQVRG1qlTxFknF6RlZOarULuWypaqmsS4AYtEamqbGcVbdSyD9VIMaI7TjGlNGWrTz26lL6SsDGxuqXNuyuzNch%2BrHJ6pnaxfDqrI3d1qyj4sXq9VutPgAWH7TLRggHPE5vUEjACskL2miRsPMQOB2LSaIAbIcNDx0gkylYpLFGNIkVJSCxpKY6ahpJp%2BPxVMIxBJ1FxZLQ6QRGZSqQBrEBcfEAOi4iTBpkS%2BMltFkSMlAE5EtSpGC6bY6KZTPThaQWVI6YIQEahVImVS4LAkGgHHgGJgyBQIM77K73ShmGwkYbSAZXTZiJaIAAjE1RhRMYgAT2kAtIztsmBYBAA8iwGMnbXSsLZWMA3Sb8JlkAQ8AA3TCWwukTAAD0wyBENhTdIUNgYJoIxDw%2BsLVID7HZvEYeCjlsgVNQ9hrqBYjYAtNnZGk12u3BtOLx%2BLRU1zxJIttracam2aWwAOfFr/Fg1RKUuqJFS0xf/q4QgkXl%2BVIVRNFQF03WIQCthAyceEFYVYjFCVpXVdU%2BVMWh5S4Wg71QlVtV1Uh9VoYMGRvaQLStUgbTtUgHUQFAMBwfAiA9SgaC4RhSxQWChFEM9pDkBQlBUTAXG0NxDBCDoLBsBwnDEmYmhqKJChMSo9HCFTAhidoSi6dJMmyYhcjwApiTJcoZPMZTIjqBsCEaTTqjs1o9M6QE0hELw2GiJdIMuZoAggPJYgWIpPM5AgmBrZBXxXXRW3sSCDH81RoqjN0OCRPgkRGS5OjROZZGwYC0QOEqyvuYwqr%2BGqoU0GFKoajESqSIYDLSPADFWEJhnxPSgSMvoCSJCK4WGkz0qYTLMGyngqGy0pwuKdqKTHGk6TIplTVZWDOX4nk5C4eDRypBBMCYLBiEoJC%2BSldUwT5ME71kXDaGw0xJQIraTTNSjrQQuiYAY71fTYr0wJ9CD/VLIMjVDBhw0jGMmzjFgEwLVN00zHM8wLHbi1Lcsm0rdsa3rRsdtbdtO0kKRU17TB%2BybQdhyB8ceMPKcGBnOc4lNJc8AS6QNy3Hc92GA8%2BF4Y8LUOyRrkvX7yKke9H2fV9xw/L8fwgP9WMAziQKh8GjfGNlubg6iEPOy7rtu0hxS4LgpUSdUPsSWRHq92R8T9n7rx2/6hComiRW1E6g%2BZCibbO0h6wjYWGTBIA%3D%3D>
It transforms them to assembler code equivalent to a switch statement and
can inline the called function f<i>().
In the code with the array of function pointers functions f<i>() are not
inlined.

However, the proposal is not about how compilers may optimize the code or
not (since this might change in the future). The proposal contains a
natural extension of the fold expression on the conditional ternary
operator and shows example to illustrate the usage.
Additional, to be natural extension, I think that the conditional ternary
fold is easier to write than creating function pointers.
Post by Barry Revzin
For your second example, is this really better than having a hashtable
from std::string to std::function<std::string(std::string const&)> and just
doing a lookup + call?
If you want to make use of hashes you could do this with the fold
expression, too.

template <typename String>
constexpr std::size_t simple_hash(String const & str)
{
std::size_t ret = 0;
for(auto const & c : str) {
ret += c;
}
return ret;
}


template<class... translators>
std::string translate_to_english_impl(
std::string_view language,
std::string_view text)
{
auto lang_hash = hash(language);
return ( ( lang_hash == simple_hash(translators::language)
&& language == translators::language)
? translators::translate_to_english(text)
: ... : throw_unknown_language<std::string>(language) );
}

If you are sure to have no hash collisions you even could omit the
comparison of the language string, i.e.

template<class... translators>
std::string translate_to_english_impl(
std::string_view language,
std::string_view text)
{
auto lang_hash = hash(language);
return ( lang_hash == simple_hash(translators::language)
? translators::translate_to_english(text)
: ... : throw_unknown_language<std::string>(language) );
}
Post by Barry Revzin
Also, it's called the conditional operator, it's not called the ternary
operator (it simply is a ternary operator).
Since the conditional operator is the only ternary operator which exists in
C++ it is often used as synonym.

However, the ternary fold applies to any ternary operator like the
conditional operator ? :
as the binary fold applies to many binary operators, i.e. +, *, etc.
However, I did not want to write the proposal with an anonymous ternary
operator op_left op_right since it makes the proposal harder to read.
For an anonymous ternary operator op_left op_right the proposal would read:
( E_left op_left E_middle op_right ... op_right E_right)
would expand to
( E_left_1 op_left E_middle _op_right ( ... ( E_left_n op_left E_middle_n
op_right E_right ) ) )
etc.
I tried to write conditional in the proposal at any place where it is
concrete to the conditional operator.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6bcbceb5-06d8-4da3-97e1-11951f55bc99%40isocpp.org.
Frank Zingsheim
2018-04-02 18:29:58 UTC
Permalink
The proposal got the paper number P1012.

Comments are welcome even more, to make this proposal a success.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/57a8bd53-3aa5-443d-b473-ff946b65e0af%40isocpp.org.
m***@gmail.com
2018-10-09 16:46:50 UTC
Permalink
Note that you can do 99% of this today


template<class... translators>
std::string translate_to_english_impl(
std::string_view language,
std::string_view text)
{
std::string ret;
if(! ((language == translators::language
? (ret = translators::translate_to_english(text), true)
: false) || ...))
throw std::runtime_error("Unknown language: " + language);

return ret;
}

And you don't even need the extra throw_ function. Granted, the fact the
return must be declared upfront is a nasty downside especially if it some
auto return type.
Post by Frank Zingsheim
The proposal got the paper number P1012.
Comments are welcome even more, to make this proposal a success.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e90d1617-e237-4e2d-ac5f-c262b7374bd0%40isocpp.org.
Frank Zingsheim
2018-10-10 17:43:46 UTC
Permalink
Thank you for the hint.

The run-time overhead of your solution in contrast to the solution in the
proposal is a default constructor + move assignment + destructor (in this
case of a std::string).
In case these three are available.
The solution from the proposal would result in a return value optimization
without any overhead and additional requirements.
Post by m***@gmail.com
Note that you can do 99% of this today
template<class... translators>
std::string translate_to_english_impl(
std::string_view language,
std::string_view text)
{
std::string ret;
if(! ((language == translators::language
? (ret = translators::translate_to_english(text), true)
: false) || ...))
throw std::runtime_error("Unknown language: " + language);
return ret;
}
And you don't even need the extra throw_ function. Granted, the fact the
return must be declared upfront is a nasty downside especially if it some
auto return type.
Post by Frank Zingsheim
The proposal got the paper number P1012.
Comments are welcome even more, to make this proposal a success.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/23981304-bda2-4303-b5c6-c74481d5d2ba%40isocpp.org.
Gašper Ažman
2018-10-10 17:52:36 UTC
Permalink
With this proposal, and for..., it's possible to implement this in language:
https://gist.github.com/ricejasonf/84c11ac6bb093c1ea8c380a9a466d8cb

Come to think of it, for... Is probably enough.
Post by Frank Zingsheim
Thank you for the hint.
The run-time overhead of your solution in contrast to the solution in the
proposal is a default constructor + move assignment + destructor (in this
case of a std::string).
In case these three are available.
The solution from the proposal would result in a return value optimization
without any overhead and additional requirements.
Post by m***@gmail.com
Note that you can do 99% of this today
template<class... translators>
std::string translate_to_english_impl(
std::string_view language,
std::string_view text)
{
std::string ret;
if(! ((language == translators::language
? (ret = translators::translate_to_english(text), true)
: false) || ...))
throw std::runtime_error("Unknown language: " + language);
return ret;
}
And you don't even need the extra throw_ function. Granted, the fact the
return must be declared upfront is a nasty downside especially if it some
auto return type.
Post by Frank Zingsheim
The proposal got the paper number P1012.
Comments are welcome even more, to make this proposal a success.
--
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/23981304-bda2-4303-b5c6-c74481d5d2ba%40isocpp.org
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/23981304-bda2-4303-b5c6-c74481d5d2ba%40isocpp.org?utm_medium=email&utm_source=footer>
.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAANG%3DkWs3hG%3DiXhKEtSjBsZ2QR0vPC8Wn-PTryJnRU3XyFWQ7w%40mail.gmail.com.
Loading...