To const or not to const? #1732
-
Here is my first range-v3 attempt (print diamond kata): [[nodiscard]] inline auto
buildDiamond(char32_t first, char32_t last, char32_t fill)
-> std::vector<std::u32string> {
using U32strings = decltype(buildDiamond(first, last, fill));
namespace views = ranges::views;
if (first > last) {
std::swap(first, last);
}
const auto length = last - first + 1;
const auto indices = views::iota(0) | views::take(length);
const auto lines = views::transform(indices, [&](char32_t idx) {
const std::array slices{
std::u32string(length - idx - 1, fill),
std::u32string{first + idx},
std::u32string(idx, fill)};
const auto left = slices | views::join;
auto right = left | views::reverse | views::drop(1); /* (a) */
return /* (b){ */ views::concat(left, right) /* }(b) */ | ranges::to<std::u32string>();
});
const auto top = lines | views::take(length);
const auto bottom = top | views::slice(0, ranges::end - 1) | views::reverse;
return views::concat(top, bottom) | ranges::to<U32strings>();
} eslint and clangd have taught me to use Most vars in the code above are Is there a reason for for Should |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
The following fix seems to work as expected: const auto left = slices | views::join | ranges::to<std::u32string>();
const auto right = left | views::reverse | views::drop(1); /* (a) */ And the following seems to work: const auto left = std::u32string(length - idx - 1, fill) +
std::u32string{first + idx} + std::u32string(idx, fill);
const auto right = left | views::reverse | views::drop(1); /* (a) */ Thus, compiler only complains when |
Beta Was this translation helpful? Give feedback.
-
After playing with Here is a working Compiler Explorer playground: and the playground code if Compiler Explorer ever goes offline: 1 #include <iostream>
2 #include <codecvt>
3 #include <string>
4 #include <vector>
5
6 #include <range/v3/range/conversion.hpp>
7 #include <range/v3/view.hpp>
8
9 inline auto operator<<(std::ostream& stream, const std::u32string_view& value)
10 -> std::ostream& {
11 std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
12 stream << conv.to_bytes(value.data());
13 return stream;
14 }
15
16 [[nodiscard]] inline auto
17 buildDiamond(char32_t first, char32_t last, char32_t fill)
18 -> std::vector<std::u32string> {
19 using U32strings = decltype(buildDiamond(first, last, fill));
20 namespace views = ranges::views;
21
22 if (first > last) {
23 std::swap(first, last);
24 }
25
26 const auto length = last - first + 1;
27
28 const auto lines = views::transform(views::iota(0), [&](char32_t idx) {
29 const std::array slices{
30 std::u32string(length - idx - 1, fill),
31 std::u32string{first + idx},
32 std::u32string(idx, fill)};
33
34 const auto left = slices | views::join;
35 auto right = left | views::reverse | views::drop(1);
36 return views::concat(left, right) | ranges::to<std::u32string>();
37 });
38
39 const auto top = lines | views::take(length);
40 auto bottom = top | views::reverse | views::drop(1);
41 return views::concat(top, bottom) | ranges::to<U32strings>();
42 }
43
44 int main() {
45 auto diamond = buildDiamond(U'А', U'Ж', U'.');
46
47 for (const auto& line : diamond) {
48 std::cout << line << "\n";
49 }
50
51 return 0;
52 } Adding const to line |
Beta Was this translation helpful? Give feedback.
-
No. Not all views are const-iterable - some views are not because they have to logically mutate, others because they cache to satisfy complexity guarantees. Regardless, this means that by using One example of a view that is sometimes not const-iterable is
Because if you write: const auto left = slices | views::join;
const auto right = left | views::reverse | views::drop(1); /* (a) */
return /* (b){ */ views::concat(left, right) /* }(b) */ | ranges::to<std::u32string>(); then |
Beta Was this translation helpful? Give feedback.
No. Not all views are const-iterable - some views are not because they have to logically mutate, others because they cache to satisfy complexity guarantees. Regardless, this means that by using
const
you make the variable not a range at all.One example of a view that is sometimes not const-iterable is
drop
, which is why:Because if you write:
then
right
is not actually…