4 ms·
"And C++ is explicitly a multi-paradigm language so there can be affordances for multiple approaches." - In other words, a jack of all trades and master of none
by grumpyprole 3y ago
"And C++ is explicitly a multi-paradigm language so there can be affordances for multiple approaches." - In other words, a jack of all trades and master of none. For a systems programming language, I'd want to be able to easily reason about where allocations, memory barriers etc are happening and I'd want an emphasis on correctness/verification (rather than ease of use). C++'s many abstractions, intended for applications programming, actually get in the way of systems programming.
- JoeAltmaier 3y agoThen use such a paradigm; it is explictly made possible.
- grumpyprole 3y agoThis is essentially the same argument as "one can write secure software in C++". If it's not enforced by the language and tooling, one can't safely assume anything.
- JoeAltmaier 3y agoUse mechanisms that are safe. You can write an incorrect program in any language. Some kind of self-discipline is important and necessary.
- erik_seaberg 3y agoWe just spent half a century proving that discipline never completely solved the problem. We can’t afford platforms in which a tiny mistake anywhere causes unpredictable failures in unrelated and correct code, and we can certainly afford the lifetime and bounds checks that prevent this.
- angiosperm 3y agoSo, use modern features that don't encourage mistakes. Most C bugs come from mistakes with pointers; in good modern C++ you rarely see pointers, and can afford to focus all the attention needed where they do appear.
- nuancebydefault 3y agoI've never seen a C++ codebase that rarely uses pointers. Any good example?
- deleted 3y ago[deleted]
- angiosperm 3y agoHere is a program that solves the New York Times puzzle "Letter Boxed". Its only uses of pointers are in processing main()'s arguments, which are provided via pointer, and mapping an input file, which Posix provides via a pointer. It does use std::string_view, which has pointers in it; the point is that you don't operate directly on the pointers, so cannot have bugs caused by misusing the pointers. Try: "g++ -std=c++20 lb.cc && ./a.out iodhuamplrnc words". #include <array> #include <bit> // popcount #include <iostream> #include <utility> #include <string_view> #include <vector> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> struct Word { std::string_view str; unsigned bits{}; static unsigned index(unsigned c) { return c - 'a'; }; // 'a'..'z' -> 0..25; others -> >25 Word(std::string_view s, unsigned accept, long long sides) : str(s) { long long prev_side{-1}, side; // Values are 0..3. First letter gets a free pass. for (char c: s) { const auto ix = index(c); if (ix < 26 && (accept & (1u << ix)) && (side = ((sides >> 2*ix) & 0x3)) != prev_side) { bits |= (1u << ix), prev_side = side; } else { str = {}; return; }}} }; int main(int ac, char** av) { auto usage = [av](){ std::cerr << "usage: " << av[0] << " abcdefghijkl [<wordlist>]\n"; }; if (!(ac == 2 || ac == 3)) { return usage(), 1; } const std::array prefixes = { "", "/usr/share/dict/", "/usr/share/dict/american-english-" }; const auto name = (ac == 3) ? av[2] : prefixes.back() + std::string{"large"}; std::string_view file; for (auto pfx = 0u; pfx != prefixes.size(); ++pfx) { int fd = ::open((prefixes[pfx] + name).c_str(), O_RDONLY); std::size_t file_size = ::lseek(fd, 0, SEEK_END); void const* addr = ::mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); if (addr != MAP_FAILED) { file = {static_cast<char const*>(addr), file_size}; break; } } if (file.empty()) { return std::cerr << av[0] << ": cannot read " << name << '\n', 3; } auto target_sum = 0u; auto sides_sum = 0ll; for (unsigned i{}, ix{}; i < 12 && (ix = Word::index(av[1][i])) < 26; ++i) { target_sum |= (1u << ix), sides_sum |= (i/3ll << 2*ix); } if (std::popcount(target_sum) != 12 || av[1][12] != '\0') { return usage(), 3; } const auto target = target_sum; const auto sides = sides_sum; const auto candidates = [target,sides,file] { std::array<std::vector<Word>, 26> candidates; for (std::string_view in = file, next; !(next = in.substr(0, in.find('\n'))).empty(); in.remove_prefix(next.size() + (next.size() < in.size()))) { // Skip past '\n' if present if (const Word word{next, target, sides}; word.str.size() >= 3) { candidates.at(Word::index(word.str.front())).push_back(word); } } return candidates; }(); std::array<std::vector<std::array<std::string_view, 2>>, 100> answers; // radix sort by length for (auto const& firsts: candidates) for (const auto first: firsts) { for (const auto second: candidates.at(Word::index(first.str.back()))) { if ((first.bits | second.bits) == target) { answers.at(first.str.size() + second.str.size()).push_back({first.str, second.str}); }} } for (auto const& of_len_N: answers) for (const auto answer: of_len_N) { std::cout << answer[0] << ' ' << answer[1] << '\n'; } }