c ++ ctor模板/公共函数(模板限制迭代器)无法编译
c++ ctor template / common function (template restrict iterator) can't compile
我正在写一个class,比如std::vector可以由n值或迭代器[first, last]构造,示例代码如下:
template<typename T>
class Test1{
public:
Test1(size_t n, const T& v){
data_ = new T[n];
for(size_t i = 0; i < n; ++n){
data_[i] = v;
}
}
template<typename Iterator>
Test1(Iterator first, Iterator last){
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
Test1(){
if(nullptr != data_){
delete[] data_;
data_ = nullptr;
}
}
T* data_;
};
用法:
Test1<int> t1(2, 0);
std::vector<int> vec{1, 2, 3};
Test1<int> t2(vec.begin(), vec.end());
但是编译错误:
...
In instantiation of Test1<T>::Test1(Iterator, Iterator) [with Iterator = int; T = int]
error: invalid type argument of unary
...
所以我的问题是如何实现这两个功能,为什么模板不能编译以及如何更改它(限制迭代器类型)?
一种不用检查迭代器的方法,也可以解决这个问题:
template<typename Iterator, typename std::enable_if<!std::is_integral<Iterator>::value, int>::type = 0>
Test1(Iterator first, Iterator last){ // integral can't use this function
cout << "using first last" << endl;
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
代码无法编译,因为 t1
正在尝试调用迭代器构造函数。
C++20
解决这个问题的最简单方法就是使用 C++20 概念 std::input_iterator
,如下所示:
template<std::input_iterator Iterator>
Test1(Iterator first, Iterator last){
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
此外,您需要删除初始化指针 (data_(n, v)
) 的无效尝试,并在 n 值构造函数中递增 i
而不是 n
。
C++11
首先我们需要一些额外的工具:
template <typename T, typename = void>
struct is_iterator {
static constexpr bool value = false;
};
template <typename T>
struct is_iterator<T, decltype(*std::declval<T>()++, void())> {
static constexpr bool value = true;
};
此自定义类型特征使用 SFINAE 检查提供的类型是否可以递增和取消引用(与您在代码中所做的方式相同)。
你可以这样使用它:
template<typename Iterator, typename std::enable_if<is_iterator<Iterator>::value, bool>::type = true>
Test1(Iterator first, Iterator last){
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
我正在写一个class,比如std::vector可以由n值或迭代器[first, last]构造,示例代码如下:
template<typename T>
class Test1{
public:
Test1(size_t n, const T& v){
data_ = new T[n];
for(size_t i = 0; i < n; ++n){
data_[i] = v;
}
}
template<typename Iterator>
Test1(Iterator first, Iterator last){
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
Test1(){
if(nullptr != data_){
delete[] data_;
data_ = nullptr;
}
}
T* data_;
};
用法:
Test1<int> t1(2, 0);
std::vector<int> vec{1, 2, 3};
Test1<int> t2(vec.begin(), vec.end());
但是编译错误:
...
In instantiation of Test1<T>::Test1(Iterator, Iterator) [with Iterator = int; T = int]
error: invalid type argument of unary
...
所以我的问题是如何实现这两个功能,为什么模板不能编译以及如何更改它(限制迭代器类型)?
一种不用检查迭代器的方法,也可以解决这个问题:
template<typename Iterator, typename std::enable_if<!std::is_integral<Iterator>::value, int>::type = 0>
Test1(Iterator first, Iterator last){ // integral can't use this function
cout << "using first last" << endl;
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
代码无法编译,因为 t1
正在尝试调用迭代器构造函数。
C++20
解决这个问题的最简单方法就是使用 C++20 概念 std::input_iterator
,如下所示:
template<std::input_iterator Iterator>
Test1(Iterator first, Iterator last){
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}
此外,您需要删除初始化指针 (data_(n, v)
) 的无效尝试,并在 n 值构造函数中递增 i
而不是 n
。
C++11
首先我们需要一些额外的工具:
template <typename T, typename = void>
struct is_iterator {
static constexpr bool value = false;
};
template <typename T>
struct is_iterator<T, decltype(*std::declval<T>()++, void())> {
static constexpr bool value = true;
};
此自定义类型特征使用 SFINAE 检查提供的类型是否可以递增和取消引用(与您在代码中所做的方式相同)。
你可以这样使用它:
template<typename Iterator, typename std::enable_if<is_iterator<Iterator>::value, bool>::type = true>
Test1(Iterator first, Iterator last){
size_t n = std::distance(first, last);
data_ = new T[n];
while(first != last){
*data_++ = *first++;
}
}