peppe
peppe

Reputation: 22744

What SFINAE tricks can I safely use on all MSVC >= 2013?

In Qt I had the brilliant (cough, cough) idea to start defining overloads of qHash (the hashing function used for QHash, one of Qt's associative containers) for Standard Library datatypes: std::basic_string, std::shared_ptr and the like.

There could be a shortcut for this process: instead of chasing "any Standard Library type that could be used as a key in QHash" and adding a qHash overload for it, I could just define qHash automatically if the type has a std::hash specialization for it (reasonably assuming that we don't want to do more than what the Standard Library does in this process).

That is, I could implement something like this using expression SFINAE:

template<typename T>
auto qHash(const T &t) -> decltype(std::hash<T>()(t)) 
{ 
    return std::hash<T>()(t); 
}

Unfortunately, although Qt demands a C++11 compiler, expression SFINAE is not allowed anywhere because MSVC does not fully support it (at the time of this writing: all MSVC versions, up to and including VS15 preview 5. Anyhow, Qt must support all the way back to 2013).

Hence, the question: is there a way to do the same, in a way that

  1. does not use expression SFINAE
  2. is guaranteed to work on all MSVC versions >= 2013?

I was thinking a plain good ol' C++98 SFINAE construction via enable_if and the like, but other SO answers (like this one) make me think that MSVC 2013 may miscompile that too, so the result becomes unacceptable again.

Upvotes: 3

Views: 155

Answers (1)

sbabbi
sbabbi

Reputation: 11181

I do not think you need expression SFINAE for this, something along these lines should work.

template<typename T>
typename std::hash<T>::result_type qHash(const T &t) 
{ 
     return std::hash<T>()(t); 
}

Or pretty much any approach that does SFINAE on hash::result_type. Unfortunately for you, hash::result_type is deprecated in C++17, but you can still #ifdef this code for MSVC 2013.

Upvotes: 2

Related Questions