循环语句的 std::is_same

我有两个结构,其方法在它们拥有的对象集合的开始和结束时返回迭代器。方法有不同的名称(这似乎是一个糟糕的应用程序架构,但这只是一个简化的模型):

struct A {
  std::vector<int>::iterator a_begin() { return v.begin(); }
  std::vector<int>::iterator a_end() { return v.end(); }

  std::vector<int> v = { 1, 2 };
};

struct B {
  std::vector<float>::iterator b_begin() { return v.begin(); }
  std::vector<float>::iterator b_end() { return v.end(); }

  std::vector<float> v = { 1.0f, 2.0f };
};

我想编写一个模板函数,它将迭代给定的对象(类型 A 或类型 B)并对其元素做一些工作。我的做法是:

template<class T>
void foo(T t) {
  if constexpr (std::is_same_v<T, A>) {
    for (auto it = t.a_begin(); it != t.a_end(); it++) {
      // a lot of stuff
    }
  } else if constexpr (std::is_same_v<T, B>) {
    for (auto it = t.b_begin(); it != t.b_end(); it++) {
      // the same stuff
    }
  }
}

因为for循环体是相同的,所以对我来说看起来有点难看。有什么办法可以改善这种情况吗?

回答

我从表面上接受你关于命名和复杂性的主张,如此抽象和桥梁。

namespace detail {
inline auto foo_begin(A& a) { return a.a_begin(); }
inline auto foo_end  (A& a) { return a.a_end();   }
inline auto foo_begin(B& b) { return b.b_begin(); }
inline auto foo_end  (B& b) { return b.b_end();   }
}
template<class T>
void foo(T t) {
for (auto it = detail::foo_begin(t); it != detail::foo_end(t); ++it) {
// the same stuff
}
}

您想要改变的操作是范围选择。因此,为您关心的类型设置一个小的重载应该可以很好地完成。

如果您经常这样做,可能值得考虑使用范围适配器。您可以手动编写它,或者使用 C++20 编写它,std::ranges::subrange您甚至可以利用这个重载集本身。

template<class T>
void foo(T t) {
for (auto &item : std::ranges::subrange(detail::foo_begin(t), detail::foo_end(t))) {
// the same stuff
}
}

以上是循环语句的 std::is_same的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>