英文:
Loop over all months in chrono
问题
需要在代码中迭代所有月份:
```C++
for (auto m = std::chrono::January; m <= std::chrono::December; m++)
std::cout << std::format(std::locale{ "pt_BR.UTF-8" }, "{:L%B}\n", m);
但是出现了无限循环,因为std::chrono::month
的增量行为是模12 + 1。因此,当循环中的变量m
达到December
(12)时,它会回绕到January
(1)。
我尝试使用std::views::iota
:
for (auto m : std::views::iota(std::chrono::January) | std::views::take(12))
std::cout << std::format(std::locale{ "pt_BR.UTF-8" }, "{:L%B}\n", m);
但是无法编译,因为std::chrono::month
不满足std::weakly_incrementable
概念。
<details>
<summary>英文:</summary>
I need iterate all months in a code:
```C++
for (auto m = std::chrono::January; m <= std::chrono::December; m++)
std::cout << std::format(std::locale { "pt_BR.UTF-8" }, "{:L%B}\n", m);
But it happens it's a infinity loop, because the std::chrono::month
increment has a modulo 12 + 1 behavior. So when the loop m
variable reaches December
(12), it wraps around to January
(1).
I tried with std::views::iota
:
for (auto m : std::views::iota(std::chrono::January) | std::views::take(12))
std::cout << std::format(std::locale { "pt_BR.UTF-8" }, "{:L%B}\n", m);
But fails to compile as std::chrono::month
don't satisfies the concept std::weakly_incrementable
.
答案1
得分: 8
你可以使用一个无符号循环!
for (unsigned i = 1; i <= 12; i++)
std::cout << std::format(std::locale { "pt_BR.UTF-8" }, "{:L%B}\n",
std::chrono::month { i });
如果你想要更高级一些,你可以为 std::chrono::month
定义 std::incrementable_traits
以与 std::views::iota
一起使用:
namespace std {
template <>
struct incrementable_traits<std::chrono::month>
: incrementable_traits<unsigned> {};
}
for (auto m : std::views::iota(std::chrono::January) | std::views::take(12))
std::cout << std::format(std::locale { "pt_BR.UTF-8" }, "{:L%B}\n", m);
请注意,我只翻译了代码部分,不包括注释或其他内容。
英文:
Your can use a unsigned loop!
for (unsigned i = 1; i <= 12; i++)
std::cout << std::format(std::locale { "pt_BR.UTF-8" }, "{:L%B}\n",
std::chrono::month { i });
If you get fancy you can define std::incrementable_traits
for std::chrono::month
to work with std::views::iota
:
namespace std {
template <>
struct incrementable_traits<std::chrono::month>
: incrementable_traits<unsigned> {};
}
for (auto m : std::views::iota(std::chrono::January) | std::views::take(12))
std::cout << std::format(std::locale { "pt_BR.UTF-8" }, "{:L%B}\n", m);
答案2
得分: 1
你可以使用一个for-range循环。
我已经取消模板化我的from_to
(包括)以便更容易看到逻辑。类似于Boost的irange。
(我还有from_til
(正常半开区间),after_to
(不常见的半开区间),和after_til
(不常见的介于区间之间)。
#include <chrono>
#include <iostream>
#include <stdexcept>
namespace {
struct from_to {
bool done{ false };
std::chrono::month hot;
std::chrono::month last;
from_to(std::chrono::month first, std::chrono::month last_) : hot{first}, last{last_} {}
auto operator*() const -> std::chrono::month { return hot; }
bool operator!=(from_to const&) const { return not done; }
void operator++() {
if (done) throw std::logic_error("increment past end");
if (hot == last) done = true;
else ++hot;
}
auto begin() const -> from_to const& { return *this; }
auto end() const -> from_to const& { return *this; }
};
auto to_cstr(std::chrono::month m) -> char const* {
switch (m.operator unsigned()) {
#define CASE(x) case std::chrono::x.operator unsigned(): return #x
CASE(January);
CASE(February);
CASE(March);
CASE(April);
CASE(May);
CASE(June);
CASE(July);
CASE(August);
CASE(September);
CASE(October);
CASE(November);
CASE(December);
#undef CASE
}
return "std::chrono::month error";
}
} // anon
int main() {
for (auto m : from_to{std::chrono::January, std::chrono::December}) {
std::cout << to_cstr(m) << "\n";
}
}
英文:
You could use a for-range loop.
I've de-templatized my from_to
(inclusive) to make it easier to see the logic. Similar to Boost irange.
(I also have from_til
(normal half-open range), after_to
(uncommon half-open range), and after_til
(uncommon betwixt-only range).)
#include <chrono>
#include <iostream>
#include <stdexcept>
namespace {
struct from_to {
bool done{ false };
std::chrono::month hot;
std::chrono::month last;
from_to(std::chrono::month first, std::chrono::month last_) : hot{first}, last{last_} {}
auto operator*() const -> std::chrono::month { return hot; }
bool operator!=(from_to const&) const { return not done; }
void operator++() {
if (done) throw std::logic_error("increment past end");
if (hot == last) done = true;
else ++hot;
}
auto begin() const -> from_to const& { return *this; }
auto end() const -> from_to const& { return *this; }
};
auto to_cstr(std::chrono::month m) -> char const* {
switch (m.operator unsigned()) {
#define CASE(x) case std::chrono::x.operator unsigned(): return #x
CASE(January);
CASE(February);
CASE(March);
CASE(April);
CASE(May);
CASE(June);
CASE(July);
CASE(August);
CASE(September);
CASE(October);
CASE(November);
CASE(December);
#undef CASE
}
return "std::chrono::month error";
}
} // anon
int main() {
for (auto m : from_to{std::chrono::January, std::chrono::December}) {
std::cout << to_cstr(m) << "\n";
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论