Given a chain of lambdas where each one captures the previous one by value:
auto l1 = [](int a, int b) { std::cout << a << ' ' << b << '\n'; };
auto l2 = [=](int a, int b) { std::cout << a << '-' << b << '\n'; l1(a, b); };
auto l3 = [=](int a, int b) { std::cout << a << '#' << b << '\n'; l2(a, b); };
auto l4 = [=](int a, int b) { std::cout << a << '%' << b << '\n'; l3(a, b); };
std::cout << sizeof(l4);
We can observe, that the resulting sizeof of l4 is equal to 1.
That makes sense to me. We are capturing lambdas by value and each of those objects has to have sizeof equal to 1, but since they are stateless, an optimization similar to [[no_unique_address]] one applies (especially since they all have unique types).
However, when I try to create a generic builder for chaining comparators, this optimization no longer takes place:
template <typename Comparator>
auto comparing_by(Comparator&& comparator) {
return comparator;
}
template <typename Comparator, typename... Comparators>
auto comparing_by(Comparator&& comparator, Comparators&&... remaining_comparators) {
return [=](auto left, auto right) {
auto const less = comparator(left, right);
auto const greater = comparator(right, left);
if (!less && !greater) {
return comparing_by(remaining_comparators...)(left, right);
}
return less;
};
}
struct triple {
int x, y, z;
};
auto main() -> int {
auto by_x = [](triple left, triple right) { return left.x < right.x; };
auto by_y = [](triple left, triple right) { return left.y < right.y; };
auto by_z = [](triple left, triple right) { return left.z < right.z; };
auto comparator = comparing_by(by_x, by_z, by_y);
std::cout << sizeof(comparator);
}
Note 1: I am aware of the fact that comparing_by is inefficient and sometimes calls the comparator in a redundant fashion.
Why in the above case the resulting sizeof of comparator is equal to 3 and not to 1? It is still stateless, after all. Where am I wrong? Or is it just a missed optimization in all of the big three compilers?
Note 2: This is purely an academic question. I am not trying to solve any particular problem.