Validating Callable Parameters
The Premise
This blog series will take you through the implementation of a type trait that can take in a callable and inspect the parameters of that callable. I will first describe how to do this using C++20 and then we can have a look at C++26 reflection.
Motivation
At CppCon 2025 I gave this lightning talk, and I have been meaning to create a blog series on the implementation of the type trait I describe in the talk for a while.
The talk itself gives a good account of the motivations for wanting to write the type trait. The TL;DW is, if we are writing algorithms, we want to make sure that functors passed to us aren’t going to be doing any expensive copies.
I meant to do a write up of the implementation in C++14 when I first implemented it for Sea of Thieves, but never quite got around to it. But since I gave this lightning talk I have had some new interest from people around how it could be implemented, and because I was quite curious as to exactly how trivial a C++26 reflection implementation would be, I think now is the time to do a deep dive.
In a nutshell, given this SortWrapper function:
template<typename ElementType, template<typename> typename ContainerTemplate, typename PredicateType>
void SortWrapper(ContainerTemplate<ElementType>& InContainer, PredicateType&& InPred)
{
static_assert(HasValidFunctorParams<PredicateType, ElementType, ElementType>);
std::ranges::sort(InContainer, InPred);
}this should compile:
std::vector<std::string> strs
{
"asdfadsflk;sdkfakghgasdf",
"plha;oldfsjhdopfghjisdop;ifhgpodfig",
"jkl;sdjfhl;kshjfggihaphsdf;ashdf"
};
SortWrapper(strs,
[](const std::string& InLeft, const std::string& InRight)
{
return InLeft.size() < InRight.size();
});and this should not:
std::vector<std::string> strs
{
"asdfadsflk;sdkfakghgasdf",
"plha;oldfsjhdopfghjisdop;ifhgpodfig",
"jkl;sdjfhl;kshjfggihaphsdf;ashdf"
};
SortWrapper(strs,
[](const std::string InLeft, const std::string InRight)
{
return InLeft.size() < InRight.size();
});Note
Note that the predicate is receiving its arguments by value and not by reference.
Diving in…
Below you will find all the different stages of the implementation. Some points to make clear first:
- All parts of the implementation are shared as godbolt links so that you can have a play around yourself.
- I am not guaranteeing that I will cover every use-case, and edge-case possible. What I can say is that everything I cover here has been good enough in the Sea of Thieves code base, and no one has ever complained about this trait incorrectly failing in years of production.
Enjoy!
C++26 - Enter Static Reflection
How easy is solving this problem with C++26 static reflection?
May 31, 2026