在 C++ 中,我正在实现
vector
类,并且在使用任何类型作为 T
的参数时遇到错误:
void insert(iterator where, size_type count, const_reference value = T()){...}
template <typename InIt>
void insert(iterator where, InIt first, InIt last){...}
执行以下操作时:
vector<int> v;
for (int i = 0; i < 5; ++i)
{
v.push_back(i + 1);
}
v.insert(v.begin() + 2, 10, 8);
v.insert(v.begin() + 4, 9);
它将
InIt
的参数视为 int
,而实际上它应该是 iterator
类型类,并且意味着调用了错误的函数,导致内部存储器错误。因此,我不得不使用 insert
参数删除 template <typename InIt>
函数,因为它破坏了我的实现。我已经用std::string
尝试过,并且出现了同样的问题。
我可以做些什么来区分这两个功能吗?
这就是 SFINAE 的用途 - 如果
InIt
不是看起来像迭代器的东西,则从重载集中删除第二个重载。在这种情况下,您只需要一个输入迭代器,它必须既可递增又可取消引用:
template <typename InIt,
typename = decltype(*std::declval<InIt&>(),
++std::declval<InIt&>())>
void insert(iterator where, InIt first, InIt last)
{
...
}
如果您要使用某些整型类型调用
insert
(以便可以将其转换为 size_t
),则 *std::declval<InIt&>
将是无效表达式,因为整型类型不可取消引用 - 因此模板推导将失败。因为 Substitution Failure Is Not An Eerror,其效果是从考虑中删除此重载,并且将调用第一个重载。
从 Concepts Iterator 参考中,您有多个选项来检查特定类型的 iterators:
(见)
自 C++20 起,可以使用概念
std::input_iterator
来约束函数。
示例:
template <std::input_iterator InIter>
void insert(iterator, InIter, InIter);