Spoiler: std::max returns a reference to one of its arguments and since you use decltype(auto) it means that clampZero will return either a reference to the parameter val or to the temporary 0. In either case this is a problem because neither of them will be alive after the function has ended.
Using auto instead of decltype(auto) to deduce the return type is safer (because it avoids references) and it's more easily understood because you can clearly see that it doesn't return a reference (unless you explicitly use & or && after). I therefore think it's best to prefer auto and only use decltype(auto) when necessary.