Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I implement max(A, max(B, max(C, D))) using fold expressions?

While trying to play around with C++17 fold expressions, I tried to implement max sizeof where result is maximum of the sizeof of types. I have an ugly fold version that uses variable and a lambda, but I am unable to think of a way to use fold expressions and std::max() to get the same result.

This is my fold version:

template<typename... T>
constexpr size_t max_sizeof(){
    size_t max=0;
    auto update_max = [&max](const size_t& size) {if (max<size) max=size; };
    (update_max(sizeof (T)), ...);
    return max;
}


static_assert(max_sizeof<int, char, double, short>() == 8);
static_assert(max_sizeof<char, float>() == sizeof(float));
static_assert(max_sizeof<int, char>() == 4);

I would like to write equivalent function using fold expressions and std::max(). For example for 3 elements it should expand to

return std::max(sizeof (A), std::max(sizeof(B), sizeof (C)));

Is it possible to do that?

like image 226
NoSenseEtAl Avatar asked Sep 25 '17 11:09

NoSenseEtAl


2 Answers

Probably not what you wanted to hear, but no. It isn't possible to do that (purely1) with fold expressions. Their very grammar simply doesn't allow for it:

[expr.prim.fold]

A fold expression performs a fold of a template parameter pack over a binary operator.

fold-expression:
  ( cast-expression fold-operator ... )
  ( ... fold-operator cast-expression )
  ( cast-expression fold-operator ... fold-operator cast-expression )
fold-operator: one of
  +   -   *   /   %   ^   &   |   <<   >> 
  +=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=  =
  ==  !=  <   >   <=  >=  &&  ||  ,    .*   ->*

Simply because a function call expression is not a binary operator in the pure grammar sense.


1 Refer to the other superb answers.

like image 147
StoryTeller - Unslander Monica Avatar answered Oct 18 '22 21:10

StoryTeller - Unslander Monica


Since nobody posted this one as an answer yet, the easiest way to do this with minimal effort is to just use the overload of std::max() that is ready-made for this problem: the one that takes an initializer_list:

template<typename... T>
constexpr size_t max_sizeof() {
    return std::max({sizeof(T)...});
}
like image 28
Barry Avatar answered Oct 18 '22 21:10

Barry