Take this
#include <range/v3/view/remove_if.hpp>
#include <range/v3/range/conversion.hpp>
#include <vector>
std::vector<int> foo(std::vector<int> v, bool(*p)(int)) {
return v | ranges::views::remove_if(p) | ranges::to_vector;
}
as compared to this
#include <range/v3/action/remove_if.hpp>
#include <vector>
std::vector<int> bar(std::vector<int> v, bool(*p)(int)) {
return std::move(v) | ranges::actions::remove_if(p);
}
No templates around, just two TUs providing each a pure function with the same signature. Given their implementation, I would expect the two functions to accomplish the same task, from the caller’s perspective. And that’s what they seem to do.
However, they compile to fairly different code, to the point that GCC (trunk, at least) produces shorter code for the latter, whereas Clang (trunk) produces shorter code for the former.
I don’t see any reason for the two functions to compile down to different code, other than “it’s too hard for the compiler to come up with the same code for both”, but what is making it so difficult? Or, if I’m wrong, why must the two functions compile down to different assembly?
And, other than benchmarking, is there a rationale why I should prefer one over the other implementation?
Complete example.