我可以在所有 MSVC >= 2013 上安全地使用哪些 SFINAE 技巧?
What SFINAE tricks can I safely use on all MSVC >= 2013?
在 Qt 中,我有一个绝妙的(咳咳)想法,开始为标准库数据类型定义 qHash
(用于 QHash 的散列函数,Qt 的关联容器之一)的重载:std::basic_string
, std::shared_ptr
等。
这个过程可能有一个捷径:与其追逐 "any Standard Library type that could be used as a key in QHash" 并为其添加 qHash
重载,我可以直接定义 qHash
如果类型具有 std::hash
对其进行专门化(合理地假设我们不想做比标准库在此过程中所做的更多的事情)。
也就是说,我可以使用表达式 SFINAE 实现类似的东西:
template<typename T>
auto qHash(const T &t) -> decltype(std::hash<T>()(t))
{
return std::hash<T>()(t);
}
不幸的是,尽管 Qt 需要 C++11 编译器,表达式 SFINAE 在任何地方都不允许 因为 MSVC 不完全支持它(在撰写本文时:所有 MSVC版本,直到并包括 VS15 预览版 5。无论如何,Qt 必须一直支持到 2013 年)。
因此,问题是:有没有办法以
- 不使用表达式 SFINAE
- 保证适用于 >= 2013 的所有 MSVC 版本?
我正在考虑通过 enable_if
等进行简单的 C++98 SFINAE 构造,但其他 SO 答案(如 this one)让我认为 MSVC 2013 可能会错误编译也是,所以结果又变得不可接受了。
我认为您不需要为此表达 SFINAE,按照这些思路应该可行。
template<typename T>
typename std::hash<T>::result_type qHash(const T &t)
{
return std::hash<T>()(t);
}
或者几乎所有在 hash::result_type
上执行 SFINAE 的方法。不幸的是,hash::result_type
在 C++17 中已弃用,但您仍然可以 #ifdef
此代码用于 MSVC 2013。
在 Qt 中,我有一个绝妙的(咳咳)想法,开始为标准库数据类型定义 qHash
(用于 QHash 的散列函数,Qt 的关联容器之一)的重载:std::basic_string
, std::shared_ptr
等。
这个过程可能有一个捷径:与其追逐 "any Standard Library type that could be used as a key in QHash" 并为其添加 qHash
重载,我可以直接定义 qHash
如果类型具有 std::hash
对其进行专门化(合理地假设我们不想做比标准库在此过程中所做的更多的事情)。
也就是说,我可以使用表达式 SFINAE 实现类似的东西:
template<typename T>
auto qHash(const T &t) -> decltype(std::hash<T>()(t))
{
return std::hash<T>()(t);
}
不幸的是,尽管 Qt 需要 C++11 编译器,表达式 SFINAE 在任何地方都不允许 因为 MSVC 不完全支持它(在撰写本文时:所有 MSVC版本,直到并包括 VS15 预览版 5。无论如何,Qt 必须一直支持到 2013 年)。
因此,问题是:有没有办法以
- 不使用表达式 SFINAE
- 保证适用于 >= 2013 的所有 MSVC 版本?
我正在考虑通过 enable_if
等进行简单的 C++98 SFINAE 构造,但其他 SO 答案(如 this one)让我认为 MSVC 2013 可能会错误编译也是,所以结果又变得不可接受了。
我认为您不需要为此表达 SFINAE,按照这些思路应该可行。
template<typename T>
typename std::hash<T>::result_type qHash(const T &t)
{
return std::hash<T>()(t);
}
或者几乎所有在 hash::result_type
上执行 SFINAE 的方法。不幸的是,hash::result_type
在 C++17 中已弃用,但您仍然可以 #ifdef
此代码用于 MSVC 2013。