Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SFINAE with C++14 return type deduction

Thanks to C++14, we'll soon be able to curtail verbose trailing return types; such as the generic min example from David Abrahams 2011 post:

template <typename T, typename U>
auto min(T x, U y)
    -> typename std::remove_reference< decltype(x < y ? x : y) >::type
{ return x < y ? x : y; }

Under C++14 the return type can be omitted, and min can be written as:

template <typename T, typename U>
auto min(T x, U y)
{ return x < y ? x : y; }

This is a simple example, however return type deduction is very useful for generic code, and can avoid much replication. My question is, for functions such as this, how do we integrate SFINAE techniques? For example, how can I use std::enable_if to restrict our min function to return types which are integral?

like image 210
user2023370 Avatar asked Jun 24 '14 21:06

user2023370


People also ask

What is Sfinae used for?

One of the primary uses of SFINAE can be found through enable_if expressions. enable_if is a set of tools, available in the Standard Library since C++11, that internally use SFINAE. They allow to include or exclude overloads from possible function templates or class template specialization.

Will concepts replace Sfinae?

So the simple answer is YES.

Can auto be a return type in C++?

In C++14, you can just use auto as a return type.

Which C++ added feature of Auto for return type of function?

C++: “auto” return type deduction The “auto” keyword used to say the compiler: “The return type of this function is declared at the end”. In C++14, the compiler deduces the return type of the methods that have “auto” as return type.


1 Answers

You can't SFINAE the function using the return type if you're using return type deduction. This is mentioned in the proposal

Since the return type is deduced by instantiating the template, if the instantiation is ill-formed, this causes an error rather than a substitution failure.

You can, however, use an extra, unused template parameter to perform SFINAE.

template <class T, class U>
auto min1(T x, U y)
{ return x < y ? x : y; }

template <class T, class U,
          class...,
          class = std::enable_if_t<std::is_integral<T>::value &&
                                   std::is_integral<U>::value>>
auto min2(T x, U y)
{
    return x < y ? x : y; 
}

struct foo {};

min1(foo{}, foo{}); // error - invalid operands to <
min1(10, 20);

min2(foo{}, foo{}); // error - no matching function min2
min2(10, 20);

Live demo

like image 116
Praetorian Avatar answered Oct 01 '22 19:10

Praetorian