我正在写一个像stl vector这样的类模板,两个构造函数是这样的:
template<class T>
vector<T>::vector(size_t count, const T&value) :bg(new T[count]),
ed(bg + count), cap(ed) {
for (auto it = bg; it != ed; ++it)
*it = value;
}//bg ed cap are all T*
template<class T>
template<class Input>
vector<T>::vector(Input first, Input second) : bg(new T[second - first]),
ed(bg + (second - first)), cap(ed) {
memcpy(bg, (void*)first, sizeof(T)*(second - first));
}
所以如果我这样做
vector<int>v(2,0)
编译器给我错误,似乎程序使用第二个构造函数,而不是第一个。谁能解释为什么?的stl矢量说
仅当InputIt满足LegacyInputIterator时,此重载才参与重载解析,以避免与重载(3)产生歧义。
因此,如何更改代码以避免这种情况?提前致谢。
选择第二个重载是因为它与Input
is类型的参数类型更好地匹配int
。具体来说,给定参数(int, int)
,重载(int, int)
比重载更好(size_t, int const&)
。请注意,如果将第一个重载的第一个参数从size_t
更改为int
,则将选择它。
如果要在Input
输入迭代器禁用功能模板重载时,可以使用以下方法利用SFINAEstd::enable_if
:
template <
typename InputIt,
typename = std::enable_if_t<
std::is_base_of_v<
std::input_iterator_tag,
typename std::iterator_traits<InputIt>::iterator_category>>>
vector(InputIt, InputIt)
{
}
您可以选择将逻辑提取到类型特征中。
template <typename T, typename = void>
struct is_input_iterator : std::false_type
{
};
template <typename T>
struct is_input_iterator<T, std::void_t<typename std::iterator_traits<T>::iterator_category>>
: std::is_base_of<
std::input_iterator_tag,
typename std::iterator_traits<T>::iterator_category>
{
};
template <typename T>
constexpr bool is_input_iterator_v = is_input_iterator<T>::value;
然后,函数定义变得更具可读性。
template <
typename InputIt,
typename = std::enable_if_t<is_input_iterator_v<InputIt>>>
vector(InputIt, InputIt)
{
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句