有没有办法确保C++中传递的模板参数是迭代器?

问题描述 投票:0回答:3

在 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
尝试过,并且出现了同样的问题。

我可以做些什么来区分这两个功能吗?

c++ templates
3个回答
6
投票

这就是 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,其效果是从考虑中删除此重载,并且将调用第一个重载。


2
投票

Concepts Iterator 参考中,您有多个选项来检查特定类型的 iterators:

C++ Concepts


0
投票

自 C++20 起,可以使用概念

std::input_iterator
来约束函数。

示例:

template <std::input_iterator InIter>
void insert(iterator, InIter, InIter);
© www.soinside.com 2019 - 2024. All rights reserved.