2

I have a info_list variable of type std::list<std::pair<std::size_t, std::byte*>> that I want to iterate and save data in binary format sequentially into a file. Here is what I tried:

void write_data() {
    std::basic_ofstream<std::byte> file("data.bin", std::ios::binary);
    for (decltype(auto) info : info_list) {
        file.write(info.second, info.first);
    }
}

The first of the std::pair is the size of the data that second pointer points to.

I'm not good with these C++ streams. The file is being saved empty. What am I doing wrong?

I'd like to avoid using C features to achieve this.

EDIT:

I tried using std::ofstream instead of std::basic_ofstream<std::byte> and it worked... Why std::basic_ofstream<std::byte> is not working here? Am I missing something?

João Paulo
  • 6,300
  • 4
  • 51
  • 80
  • 3
    I'd be interested to know how to do this ... but my general impression is that going outside the standard-defined streams (char, wchar_t) is not always as trivial as you would think/hope. [This answer](https://stackoverflow.com/a/43738691/751579) is interesting reading (though it is 3 yrs old). Keep using `std::ostream::write` until C++ is improved (or fixed, depending on your point of view). – davidbak Mar 29 '21 at 02:12
  • 1
    On a side note, in the `for` loop, `decltype(auto)` should be `auto&`: `for (auto &info : info_list)` – Remy Lebeau Mar 29 '21 at 05:30
  • @RemyLebeau Why? If both `decltype(auto)` and `auto&` are deducted to the same type in this situation. – João Paulo Mar 29 '21 at 11:44
  • @JoãoPaulo [What are some uses of decltype(auto)?](https://stackoverflow.com/questions/24109737/) Not one mention of using `decltype(auto)` in a range-for loop – Remy Lebeau Mar 29 '21 at 14:27
  • Is there something in the standard that does not allow me to use `decltype(auto)` in a declaration since it's a placeholder type specifier just like `auto`? I think this code with `decltype(auto)` is well-formed. If it's just not convenient to use `decltype(auto)` in this situation, ok, I can agree with you. – João Paulo Mar 29 '21 at 15:04
  • 2
    @RemyLebeau also from the official cpp [FAQ](https://isocpp.org/wiki/faq/cpp14-language#decltype-auto): "(...) However, decltype(auto) is not intended to be a widely used feature beyond that. In particular, **although it can be used to declare local variables, doing that is probably just an antipattern** since **a local variable’s reference-ness should not depend on the initialization expression**". So yes, "being legal" doesn't mean it's good to use. – Lorah Attkins Apr 03 '21 at 08:25

1 Answers1

2

Here is what you're missing: When using std::basic_ofstream<std::byte>, you are actually instantiating std::basic_ofstream<std::byte, std::char_traits<std::byte>>.

The problem lies with std::char_traits, since the Standard specializations (types for which the behavior is well-defined) are:

std::char_traits<char>
std::char_traits<wchar_t>
std::char_traits<char16_t>
std::char_traits<char32_t>
std::char_traits<char8_t>

Unlike std::ofstream that uses a specialization defined in the standard library (namely std::char_traits<char>), your code uses std::char_traits<std::byte>. To proceed with such an implementation, you have to provide the missing specialization.

Lorah Attkins
  • 5,331
  • 3
  • 29
  • 63