Decltype (auto), return type and sfinae: can we mix them?

Consider the following code:

auto f() -> decltype(auto) { /* do whatever you want here */ } int main() { f(); } 

The return type is displayed and decltype(auto) used as the return type.
The code below is a slightly modified (actually, sfinae'd) version:

 struct S { static void f() {} }; struct T {}; template<typename U> auto f(int) -> decltype(U::f(), void()) { // do whatever you want here } template<typename> auto f(char) -> decltype(auto) { // do whatever you want here } int main() { f<S>(0); f<T>(0); } 

If you pass the exam for this function:

 template<typename U> auto f(int) -> decltype(U::f(), void()) { // do whatever you want here } 

Question: is it possible to use a return type of return to execute sfinae and still have a return type?
I mean something like the code below (this does not work, of course):

 template<typename U> auto f(int) -> decltype(U::f(), auto) { // do whatever you want here } 

Note. I'm not looking for alternative approaches with template options, I know them, and I'm just interested to know if this is a viable solution.

+5
source share
3 answers

decltype(auto) is an integral construct (almost as if it were a keyword, such as decltype_auto ). In addition, auto cannot be used as a standalone object inside decltype(x) , because this will prevent a valid x expression.

+4
source

Not an answer, but a possible workaround using void_t.

At least as DRY as you want:

 template<typename... Ts> struct make_void { typedef void type;}; template<typename... Ts> using void_t = typename make_void<Ts...>::type; struct S { static int f() { return 3; } }; struct P { static int p() { return 4; } }; struct T {}; template<typename U, void_t<decltype(U::f())>* = nullptr > auto f(int) -> decltype(auto) { // do whatever you want here std::cout << "f1\n"; return U::f(); } template<typename U, void_t<decltype(U::p())>* = nullptr > auto f(int) -> decltype(auto) { // do whatever you want here std::cout << "f3\n"; return U::p(); } template<typename> auto f(char) -> decltype(auto) { std::cout << "f2\n"; // do whatever you want here } int main() { std::cout << f<S>(0) << '\n'; std::cout << f<P>(0) << '\n'; f<T>(0); } 
0
source

You can add another parameter of type void(*)() to the function and assign it a lambda with the return type as the default argument, therefore SFINAE can be applied via lambda:

 template<typename U> decltype(auto) f(int, void(*)() = []()->decltype(U::f(), void()) {}) { // do whatever you want here } 
0
source

Source: https://habr.com/ru/post/1257372/


All Articles