我想使用宏来创建更简单的源代码
这是我的代码
constexpr auto make_index_sequence_array(size_t i ,std::index_sequence<arg...>) {
return std::array<size_t, sizeof...(arg)> {i+arg...};
}
#define RANGE(start , end) make_index_sequence_array(start,std::make_index_sequence<end-start>{})
#define ZeroTo(end) RANGE(0 , end)
#define Repeat(end) for(auto itr : RANGE(0 , end))
void main() {
vector<int> a = { 1,2,3 };
for (auto row : RANGE(0,a.size()))
cout << std::setw(4) << a[row];
cout << '\n';
}
我知道我可以使用:
void main() {
vector<int> a = { 1,2,3 };
for (auto itr: a)
cout << std::setw(4) << itr;
cout << '\n';
}
但这是一个简单的例子,我希望在更多情况下使用这种风格。 编译时的错误是:
错误C2975'_Size':'std :: make_index_sequence'的模板参数无效,预期编译时常量表达式
如何使用我的宏?或者甚至有可能吗?
答案 0 :(得分:2)
我的建议是你使用迭代器,我在下面写了一个例子。像这样的东西可以在C ++&lt; C ++ 17:
#include <iostream>
template <class T>
struct RangeIter {
RangeIter(T from, T to, T curr ) :
_from(from), _to(to), _curr(curr) {
}
T operator*() const {
return _curr;
}
T operator++() {
++_curr;
return _curr;
}
bool operator==(const RangeIter & other) {
assert(_from == other._from && _to == other._to);
return _curr == other._curr;
}
bool operator!=(const RangeIter & other) {
return !(_curr == other._curr);
}
T _from, _to, _curr;
};
template <class T>
struct Range {
Range(T from, T to) : _from(from), _to(to) {}
RangeIter<T> begin() { return RangeIter<T>(_from, _to, _from); }
RangeIter<T> end() {
return RangeIter<T>(_from, _to, _to);
}
T _from, _to;
};
template <class T>
Range<T> makeRange(T to, T from) {
return Range<T>(to, from);
}
int main() {
for (auto i : makeRange(0, 10)) {
std::cout << i << std::endl;
}
}
对于C ++ 17,您可以为begin和end迭代器使用不同的类型,并对此进行改进。你可以使用哨兵。你可以看看这里:How the new range-based for loop in C++17 helps Ranges TS?
这里只有C ++ - 17解决方案:
#include <iostream>
template <class T>
struct RangeSentinel {
RangeSentinel(T stopVal) : _stopVal(stopVal) {}
T _stopVal;
};
template <class T>
struct RangeIter {
RangeIter(T from, T to, T curr) :
_from(from), _to(to), _curr(curr) {
}
T operator*() const {
return _curr;
}
T operator++() {
++_curr;
return _curr;
}
bool operator==(const RangeSentinel<T> & other) {
assert(_from == other._from && _to == other._to);
return _curr == other._stopVal;
}
bool operator!=(const RangeSentinel<T> & other) {
return !(_curr == other._stopVal);
}
T _from, _to, _curr;
};
template <class T>
struct Range {
Range(T from, T to) : _from(from), _to(to) {}
RangeIter<T> begin() { return RangeIter<T>(_from, _to, _from); }
RangeSentinel<T> end() {
return RangeSentinel<T>(_to);
}
T _from, _to;
};
template <class T>
Range<T> makeRange(T to, T from) {
return Range<T>(to, from);
}
int main() {
for (auto i : makeRange(0, 10)) {
std::cout << i << std::endl;
}
}
正如您所看到的,在C ++ 17解决方案中,我不需要再次存储_from和_to变量,因为sentinel是一个不同的类型。