If you try something relatively simple in C++20 it implodes with unhelpful error message spam.
int main() {
auto as = std::vector{1,3,24,};
auto bs = std::vector{1,4,10};
auto cs = std::vector<float>{};
std::ranges::transform(as, bs, std::back_inserter(cs), std::max);
std::ranges::copy(cs, std::ostream_iterator<float>(std::cout, " "));
}
Reason is that std::max is templated function, so it just does not work.
This can be easily worked around by making argument a lambda or making a small helper functor.
But I was wondering if C++ concepts could be used to tell what template instantiation what we want?
For example, we hack some requires statement that says that if functor argument is template then the template arguments of that functor must match the container value_type.
I doubt that is possible, since I think that exact type of functor must be known before template overload resolution and constraint cheks kick in, in other words, there is no "backpropagation" of information from concepts to callsite.
But I am not sure so I decided to ask.
If you want to know what I have tried, here is my code, but it is very broken, I am incapable of writing template template arguments code...
But anyways I hope it illustrates the idea...
template<typename C, typename F>
struct xtransform
{
xtransform(C& c, F f) : c_(c), f_(f){}
void operator()(){
}
C c_;
F f_;
};
template<typename C, template<typename> typename F, typename FArg>
requires requires {
std::is_same_v<typename C::value_type, FArg>;
}
struct xtransform<C, F<FArg>>
{
xtransform(C& c, F<FArg> f) : c_(c), f_(f){}
void operator()(C& c, F<FArg> f){
}
C c_;
F<FArg> f_;
};
std::maxnames a template. You can't get a concrete thing from that. I think it could be fixed if an overload was added that take a template template parameter.std::maxa neibloid, although that breaks existing code.