Search code examples
c++conditional-operatorfunctor

is there a predefined functor for conditional operator in c++?


Predefined functors are used as wrappers for operators in c++ to use, for example, in STL algorithms. There seems to be a wrapper for all operators except conditional. Is it missing? If yes, why?

Below is the potential usage for such functor with std::transform algorithm

#include <algorithm>
#include <iostream>
#include <vector>
#include <ctime>

int main() {
   std::vector<int> v1(10), v2(10), v3(10);

   srand(static_cast<unsigned>(time(nullptr)));

   // generates random values in two vectors
   generate(v1.begin(), v1.end(), []{return rand()%100;});
   generate(v2.begin(), v2.end(), []{return rand()%100;});

   // selects the larger element out of corresponding two
   transform(v1.begin(), v1.end(), v2.begin(), v3.begin(),
             [](int i, int j){ if (i>j) return i; else return j;});

   // equivalent code with potential conditional functor
   // transform(v1.begin(), v1.end(), v2.begin(), v3.begin(),
   //           conditional<>(greater<>)());

   // prints the selected values
   for(auto e: v3) std::cout << e << ", "; std::cout << endl;
}


Solution

  • There seems to be a wrapper for all operators except conditional. Is it missing?

    Yes, it is missing. No, it is not the only one missing. There are also no wrappers for the (pre-/post-)increment, (pre-/post-)decrement, subscript, indirection, member access, and comma operators. Also the address of operator, unless you count std::addressof (which is not affected by operator&).

    If yes, why?

    One reason is that it is not an arithmetic or a logical operator. According to cppreference.com, the operator function objects are for "common arithmetic and logical operations" (plus the function call operator, which is mentioned earlier on the linked page).

    Another reason is that the link to standard algorithms is weak. The arithmetic operators directly transform their parameters. The logical operators directly compare their parameters. In contrast, your example of using the comparison operator is indirect, in that the parameters have to go through something else (std::greater) in addition to being used as operands. The more you deviate from a direct wrapper, the more likely that your implementation will be weak/wanting.

    Stepping away from your specific example, it becomes less clear why this setup should be considered equivalent to "the comparison operator". In general, the first operand (the boolean condition) does not have to depend on the other two operands, so your proposed approach is more of a specialization of the comparison operator than a wrapper for it. Plus, such a specialization would have limited usefulness since it could not transform the parameters, only select one of them. Wrapping the operator in a lambda is much more flexible and powerful. There is not a lot of benefit here for the cost of defining and implementing this specialized wrapper.