在自定义向量类中调用了错误的构造函数
Wrong constructor called in custom vector class
我是C++的新手,作为一个学习练习,我正在创建自己的简单向量类。
它似乎工作得很好,除了当我创建一个Vec对象试图使用
Vec(size_type n,const T&val=T(((构造函数,它希望使用模板化的构造函数,该构造函数应该使用两个迭代器/指针,并给我错误。
我相信我理解为什么会发生这种情况,但我想不出一种方法,在不改变类的使用方式的情况下,让它变得不那么模糊。我希望使用与std::vector相同的方法。
如何调用正确的构造函数?std::矢量如何避免这个问题?
Vec.h
//#includes: <algorithm> <cstddef> <memory>
template <class T> class Vec
{
public:
//typedefs for iterator, size_type....
//just used T* for iterator
Vec() { create(); }
Vec(const Vec& v) { create(v.begin(), v.end()); }
explicit Vec(size_type n, const T& val = T()) { create(n, val); }
template <class InputIt>
Vec(InputIt first, InputIt last) { create(first, last); }
~Vec() { uncreate(); }
T& operator[](size_type i) { return data[i]; }
const T& operator[](size_type i) const { return data[i]; }
Vec& operator=(const Vec&);
//functions such as begin(), size(), etc...
private:
iterator data;
iterator avail;
iterator limit;
std::allocator<T> alloc;
void create();
void create(size_type, const T&);
template <class InputIt>
void create(InputIt first, InputIt last)
{
data = alloc.allocate(last - first);
limit = avail = std::uninitialized_copy(first, last, data);
}
void uncreate();
void grow();
void unchecked_append(const T&);
};
template <class T>
Vec<T>& Vec<T>::operator=(const Vec& rhs)
{
if (&rhs != this)
{
uncreate();
create(rhs.begin(), rhs.end());
}
return *this;
}
template <class T> void Vec<T>::create()
{
data = avail = limit = 0;
}
template <class T> void Vec<T>::create(size_type n, const T& val)
{
data = alloc.allocate(n);
limit = avail = data + n;
std::uninitialized_fill(data, limit, val);
}
template <class T>
void Vec<T>::create(const_iterator i, const_iterator j)
{
data = alloc.allocate(j - i);
limit = avail = std::uninitialized_copy(i, j, data);
}
template <class T> void Vec<T>::uncreate()
{
if (data)
{
iterator it = avail;
while (it != data)
alloc.destroy(--it);
alloc.deallocate(data, limit - data);
}
data = limit = avail = 0;
}
//left out what I didn't think was relevant
除了我上面提到的情况外,它似乎运行良好。
main.cpp
#include "Vec.h"
main()
{
Vec<int> v1(10, 100);
}
我收到错误:
||===编译:在Vec类中调试(编译器:GNU GCC编译器(===|c: \program files\codeblocks\mingw\bin\。。\lib\gcc\mingw32\4.7.1\include\c++\bits\stl_uniinitialized.h||在'_ForwardIterator std::uninitialized_copy(_InputIterator,_InputIt erator,_ForwardIt erator(的实例化中[其中_InputIterator=int;_Forward Iterator=int*]':|F: \CBProjects\Accelerated C++\ Programming with Classes\Vec Class\Vec.h|58|必需自'void Vec::create(InputIt,InputIt([with InputIt=int;T=int]'|F: \CBProjects\Accelerated C++\ Programming with Classes\Vec Class\Vec.h|24|必需自"Vec::Vec(InputIt,InputIt([with InputIt=int;T=int]"|F: \CBProjects\Accelerated C++\ Programming with Classes\Vec Class\main.cpp|9|此处为必填项|c: \program files\codeblocks\mingw\bin\。。\lib\gcc\mingw32\4.7.1\include\c++\bits\stl_uniinitialized.h|113|错误:"struct-std::iterator_traits"中没有名为"value_type"的类型|||===生成失败:1个错误,4个警告(0分钟,0秒(===|
这是我第一次在这里提问。我希望我问得恰当,并提供了足够的信息。如果我在这个过程中犯了错误,请告诉我,并感谢你能提供的任何帮助。
编辑:
对于任何想知道我最终做了什么的人。我更改了模板化的构造函数,这样它就不会被算术参数调用(因为它只适用于迭代器/指针(。
template <class InputIt>
Vec(InputIt first, InputIt last,
typename std::enable_if<!std::is_arithmetic<InputIt>::value>::type* = 0) {create(first, last); }
它看起来很好用,但实际上我对enable_if不是很熟悉,所以如果有人知道这种方法的任何危险,请告诉我。
之所以选择模板化构造函数,是因为它与参数更匹配。
查看向量构造函数的文档,您将看到一个注意事项,即只有当参数满足InputIterator
的要求时,该构造函数才会参与重载解析。这通常是通过使用SFINAE禁用过载来实现的。以下是libcpp如何实现这一点。我试着去掉一些不必要的部分,并调整了命名约定,以提高可读性。
在实际实现中,此构造函数的常见定义如下:
template <class InputIterator>
vector(InputIterator first, InputIterator last,
typename enable_if<is_input_iterator <InputIterator>::value>::type* = 0);
template <class InputIterator>
vector(InputIterator first, InputIterator last, const allocator_type& a,
typename enable_if<is_input_iterator <InputIterator>::value>::type* = 0);
我去掉了进一步区分InputIterator
和ForwardIterator
的不必要部分。SFINAE的重要部分是enable_if及其参数。
以下是is_input_iterator
:的必要定义
template <class Tp, class Up,
bool = has_iterator_category<iterator_traits<Tp> >::value>
struct has_iterator_category_convertible_to
// either integral_constant<bool, false> or integral_constant<bool, true>
: public integral_constant<
bool,
is_convertible<typename iterator_traits<Tp>::iterator_category, Up>::value
>
{};
// specialization for has_iterator_category<iterator_traits<Tp> >::value == false
template <class Tp, class Up>
struct has_iterator_category_convertible_to<Tp, Up, false> : public false_type {};
template <class Tp>
struct is_input_iterator
: public has_iterator_category_convertible_to<Tp, input_iterator_tag> {};
它的本质是检查给定类型是否具有可以转换为input_iterator_tag
的iterator_category
标记。
has_iterator_category
更加晦涩难懂:
template <class Tp>
struct has_iterator_category
{
private:
struct two {char lx; char lxx;};
template <class Up> static two test(...);
template <class Up> static char test(typename Up::iterator_category* = 0);
public:
static const bool value = sizeof(test<Tp>(0)) == 1;
};
它用于检查给定类型是否具有名为iterator_category
的成员。如果答案是no
,则has_iterator_category_convertible_to
将简单地默认为false_type
。如果不这样做,将访问不存在的名称,并触发硬编译器错误,这不是您在SFINAE中想要做的。
- "error: no matching function for call to"构造函数错误
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 模板,函数使用错误的构造函数来复制我的对象
- C++ OpenCV 卡尔曼滤波器构造函数错误
- 不命名构造函数和析构函数上的类型错误
- 处理简单 cpp 类构造函数中的错误
- 类和构造函数中的函数根本不起作用,并且不返回任何错误
- 链接器错误:无法解析构造函数
- 当我尝试通过构造函数分配 char 数组时出现错误
- 没有参数的构造函数给我错误
- 使用复制构造函数的程序输出错误
- 默认构造函数上的分段错误
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- 为什么定义复制构造函数会给我错误:无法将类型 'obj&' 的非常量左值引用绑定到类型为"obj"的右值?
- 带有 QWidget 的分段错误构造函数.Qt/C++
- C++错误构造函数参数
- 错误:构造函数未命名类型
- 错误:构造函数在此上下文中受到保护
- 没有匹配的函数错误C++构造函数
- 错误:构造函数的多个定义