Consider the following function:
template <class T>
constexpr /* something */ f(T&& x) {
// do something
}
and let's say that I want to do sfinae based on the type of a forwarded argument passed to a function called myfunction
. One way to achieve this is:
template <class T>
constexpr auto f(T&& x) -> decltype(myfunction(std::forward<T>(x))) {
// do something
}
instead of doing this, is there a way to do it at the template level:
// This code won't compile
template <class T, class R = decltype(myfunction(std::forward<T>(x)))>
constexpr R f(T&& x) {
// do something
}
except that I don't have access to x
yet so this code won't compile. Is there a way to achieve this only based on T
(possibly using std::declval
)?
Note: this is not an X/Y problem, it's just an example to illustrate where this situation happen: I don't know how to do SFINAE with forwarding without accessing the variable because for me the behavior of std::forward
is still a little mysterious.
Yes, std::declval
is indeed the key:
template <class T, class R = decltype(myfunction(std::declval<T>()))>
constexpr R f(T&& x) {
// do something
}
This will either SFINAE out or R
will be the return type of whichever overload of myfunction
is chosen.
Your question makes it appear to me that you need a refresher on how reference-collapsing works; I suggest reading up in that area (this seems like a good starting point).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With