c++ - 特定类型的迭代器 - 函数参数 - 元编程
问题描述
我正在尝试编写一个函数,该函数采用给定类型的(前向)迭代器。使用 SFINAE 真的很有帮助。我想出了以下(不工作)解决方案:
template<class ForwardIterator,
typename std::enable_if<
std::is_same<typename std::iterator_traits<ForwardIterator>::value_type, int>::value
>::type
>
inline void foo(ForwardIterator begin, ForwardIterator end)
{
}
在这种情况下, foo 应该可以使用std::vector<int>::iterator
或仅通过提供原始 int 指针来调用。问题是,它不像我预期的那样工作。编译器(msvc 2019)总是抱怨找不到匹配的重载函数。
该代码有什么问题?
解决方案
这不起作用的原因是因为如果enable_if
得到一个真实的值,你的声明将解析为
template<class ForwardIterator, void>
这不是声明模板的有效方式。如果它改为说class = void
它将有一个默认值为 void 的未命名参数,它将起作用。
template<class ForwardIterator,
class = typename std::enable_if<
std::is_same<typename std::iterator_traits<ForwardIterator>::value_type, int>::value
>::type>
然而,这带来了另一个问题。模板参数的默认值不是其签名的一部分。因此,如果我们尝试在我们替换的地方添加一个重载,由于两个模板函数具有相同的签名,我们会得到一个错误int
。double
为了解决第二个问题,我们改为将第二个参数设为非类型参数。这将使签名相对于彼此是唯一的。
template<class ForwardIterator,
typename std::enable_if<
std::is_same<typename std::iterator_traits<ForwardIterator>::value_type, int>::value
>::type* = nullptr>
现在,如果enable_if
成功,我们会得到void*
一个默认值为 of 的非类型参数,如果我们愿意nullptr
,我们可以在其中添加具有不同要求的重载。enable_if
SFINAE 通常用于根据标准在不同功能之间进行选择,如果您只想限制模板static_assert
很可能是更好的选择。
更容易编写,更容易阅读,并且当编译失败时,您会收到更具描述性的错误消息。
推荐阅读
- node.js - PATH设置不生效
- c# - 使用 C# 2017 在 WebBroswer 控件中旋转图像
- javascript - 从日期范围计算工作日
- angular - 如果 URL 是手动编写的,则 Angular 刷新应用程序
- java - 尝试使用eclipse和hibernate 5连接到mysql数据库
- date - 在 Neo4J 中使用 Cypher 将 DateTime 转换为 Epoch 毫秒
- reactjs - 服务器端使用 Apollo GraphQL 和 React 在同构应用程序中渲染请求后清空缓存
- google-app-engine - Cron jobs don't get updated after deploying a new version
- c++ - 如何将“this”的生命周期移动到 C++ 中的另一个对象中?
- sqlite - SqliteConnection Xamarin 形成未处理的异常?