Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Folding expressions in C++17 - Usecase for comparison operators

According to N4295 C++17 will allow me to calculate the sum of an unknown number of arguments thus:

template<typename ... T>
int sum(T...t)
{
    return (... + t);
}

The document further states that I could use operators such as == or > instead of +. Can anybody come up with a sensible example of when I would want to use == or > in such a construct?

(I realize that people can define == and > to do strange things to strange classes, but surely that violates good practice. Writing a > b > c > d is hardly ever a good idea, is it?)

like image 790
oz1cz Avatar asked May 21 '16 09:05

oz1cz


2 Answers

I would be an interesting feature if chained comparisons where handled like in Python where a < b < c is interpreted as a < b and b < c with a single evaluation of b. Unfortunately, this is not the case in C++ and even in strange cases, folding comparison operators indeed hardly makes sense.

Note that there was a proposal (P0313) to actually remove the operators ==, !=, <, >, <= and >= from the operators handled by fold expressions altogether. It has been discussed during the June 2016 committee meeting in Oulu. The motivation for the removal was rather brief:

Comparison operators don't make much sense in fold-expressions; they expand into expressions that have surprising effects, and are thus useful for dsl-metaprogrammers only. [...] It would be nice to be able to fix expressions like a < b < c. That would require a time machine. Not repeating the problem for fold-expressions seems doable.

That said the proposal was rejected.

like image 197
Morwenn Avatar answered Oct 15 '22 10:10

Morwenn


This is not a "direct folding of == alone" but rather a "&& folded with an expression involving ==". However this is the solution I use to compare values and maybe this is also the kind of application you had in mind.

This works for me, for both g++ and clang++

template <typename TYPE, typename... TYPE_TAIL>
constexpr bool same_value([[maybe_unused]] TYPE value, TYPE_TAIL... value_tail)
{
  return (... && (value == value_tail));
}

static_assert(same_value(3));
static_assert(same_value(3, 3));
static_assert(!same_value(3, 1));
static_assert(same_value(3, 3, 3));
static_assert(!same_value(3, 1, 3));

int main() {}

Compilation:

clang++ -std=c++1z testFold.cpp -o testFold

(version: clang version 5.0.0-+rc2-1 (tags/RELEASE_500/rc2))

or

g++ -std=c++17 testFold.cpp -o testFold

(version: g++ (Debian 7.2.0-8) 7.2.0)

The [[maybe_unused]] prevents compiler to warn you when same_value(one_arg) is called with only one argument as in that case the function returns the neutral value for the && operator (which is true).

like image 2
Picaud Vincent Avatar answered Oct 15 '22 10:10

Picaud Vincent