mirror of
https://github.com/zebrajr/pytorch.git
synced 2026-01-15 12:15:51 +00:00
constexpr all the things in irange.h (#147633)
I got complaints while irangeifying some files in ExecuTorch that irange could not be used in a constexpr function. This made the complaints go away. I added a constexpr function in irange_test that used to fail to build with `error: variable of non-literal type 'iterator' (aka 'integer_iterator<int, true>') cannot be defined in a constexpr function before C++23` and now builds fine. Differential Revision: [D69959614](https://our.internmc.facebook.com/intern/diff/D69959614/) Pull Request resolved: https://github.com/pytorch/pytorch/pull/147633 Approved by: https://github.com/albanD
This commit is contained in:
committed by
PyTorch MergeBot
parent
6e0b09728a
commit
84fcf1bb11
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
using namespace ::testing;
|
||||
|
||||
TEST(irangeTest, range_test) {
|
||||
@@ -56,3 +58,31 @@ TEST(irange, empty_reverse_range_one_input) {
|
||||
const std::vector<int> correct = {};
|
||||
ASSERT_EQ(test_vec, correct);
|
||||
}
|
||||
|
||||
constexpr std::array<int, 3> toy_iota() {
|
||||
std::array<int, 3> result = {0};
|
||||
for (const auto i : c10::irange(3)) {
|
||||
result[i] = i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr std::array<int, 3> toy_iota_with_start(int start) {
|
||||
std::array<int, 3> result = {0};
|
||||
for (const auto i : c10::irange(start, start + 3)) {
|
||||
result[i - start] = i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST(irange, constexpr_ok) {
|
||||
constexpr auto arr = toy_iota();
|
||||
static_assert(arr[0] == 0);
|
||||
static_assert(arr[1] == 1);
|
||||
static_assert(arr[2] == 2);
|
||||
|
||||
constexpr auto arr2 = toy_iota_with_start(4);
|
||||
static_assert(arr2[0] == 4);
|
||||
static_assert(arr2[1] == 5);
|
||||
static_assert(arr2[2] == 6);
|
||||
}
|
||||
|
||||
@@ -24,28 +24,28 @@ struct integer_iterator {
|
||||
using pointer = I*;
|
||||
using reference = I&;
|
||||
|
||||
explicit integer_iterator(I value) : value(value) {}
|
||||
explicit constexpr integer_iterator(I value) : value(value) {}
|
||||
|
||||
I operator*() const {
|
||||
constexpr I operator*() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
I const* operator->() const {
|
||||
constexpr I const* operator->() const {
|
||||
return &value;
|
||||
}
|
||||
|
||||
integer_iterator& operator++() {
|
||||
constexpr integer_iterator& operator++() {
|
||||
++value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
integer_iterator operator++(int) {
|
||||
constexpr integer_iterator operator++(int) {
|
||||
const auto copy = *this;
|
||||
++*this;
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool operator==(const integer_iterator& other) const {
|
||||
constexpr bool operator==(const integer_iterator& other) const {
|
||||
if constexpr (one_sided) {
|
||||
// Range-for loops' end test is `begin != end`, not `begin <
|
||||
// end`. To handle `c10::irange(n)` where n < 0 (which should be
|
||||
@@ -64,7 +64,7 @@ struct integer_iterator {
|
||||
return false; // Horrible hack
|
||||
}
|
||||
|
||||
bool operator!=(const integer_iterator& other) const {
|
||||
constexpr bool operator!=(const integer_iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
@@ -80,12 +80,12 @@ template <
|
||||
std::enable_if_t<std::is_integral_v<I>, bool> = true>
|
||||
struct integer_range {
|
||||
public:
|
||||
integer_range(I begin, I end) : begin_(begin), end_(end) {}
|
||||
constexpr integer_range(I begin, I end) : begin_(begin), end_(end) {}
|
||||
using iterator = detail::integer_iterator<I, one_sided>;
|
||||
iterator begin() const {
|
||||
constexpr iterator begin() const {
|
||||
return begin_;
|
||||
}
|
||||
iterator end() const {
|
||||
constexpr iterator end() const {
|
||||
return end_;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ template <
|
||||
typename Integer2,
|
||||
std::enable_if_t<std::is_integral_v<Integer1>, bool> = true,
|
||||
std::enable_if_t<std::is_integral_v<Integer2>, bool> = true>
|
||||
integer_range<Integer2> irange(Integer1 begin, Integer2 end) {
|
||||
constexpr integer_range<Integer2> irange(Integer1 begin, Integer2 end) {
|
||||
// If end<=begin then the range is empty; we can achieve this effect by
|
||||
// choosing the larger of {begin, end} as the loop terminator
|
||||
return {
|
||||
@@ -116,7 +116,7 @@ integer_range<Integer2> irange(Integer1 begin, Integer2 end) {
|
||||
template <
|
||||
typename Integer,
|
||||
std::enable_if_t<std::is_integral_v<Integer>, bool> = true>
|
||||
integer_range<Integer, true> irange(Integer end) {
|
||||
constexpr integer_range<Integer, true> irange(Integer end) {
|
||||
return {Integer(), end};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user