ToruNiina / toml11

TOML for Modern C++

Home Page:https://toruniina.github.io/toml11/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TOML11_DEFINE_CONVERSION_NON_INTRUSIVE save files

keepitsimle opened this issue · comments

TOML11_DEFINE_CONVERSION_NON_INTRUSIVE

get value fine, but write values to file failed.

  • toml11 version 3.7.0
  • gcc version 9.4.0

here is code:

#include "toml.hpp"
#include <fstream>
#include <iostream>
namespace foo
{
class device
{
public:
    int heart;
};
} // namespace foo

TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(foo::device, heart)

int main()
{
    auto file = toml::parse("cfg.toml");
    auto f = toml::find<foo::device>(file, "device");
    f.heart = 1;
    std::ofstream ofs("cfg1.toml");
    ofs << file;
    ofs.close();
    return 0;
}

and the cfg.toml

[device]
heart = 98
port = 1234

last cfg1.toml

[device]
port = 1234
heart = 98

Unfortunately, it does not work in that way.

You converted the data from toml::value to foo::device. This conversion inevitably copies the value because the converted types are not a reference nor pointer. You cannot modify the original through copied value because they are located in different regions of memory.

If you want to modify the value, you need to modify the original data. There are several ways to do that.

  1. you can modify the value directly.
int main()
{
    auto file = toml::parse("cfg.toml");

    file["device"]["heart"] = 1;

    std::ofstream ofs("cfg1.toml");
    ofs << file;
    ofs.close();
    return 0;
}
  1. you can take a non-const (mutable) reference to the data
int main()
{
    auto file = toml::parse("cfg.toml");

    auto& heart = toml::find(file, "device", "heart");

    heart = 1;

    std::ofstream ofs("cfg1.toml");
    ofs << file;
    ofs.close();
    return 0;
}
  1. you can substitute modified foo::device to "device" table.
int main()
{
    auto file = toml::parse("cfg.toml");

    auto f = toml::find<foo::device>(file, "device");
    f.heart = 1;

    file["device"] = f;

    std::ofstream ofs("cfg1.toml");
    ofs << file;
    ofs.close();
    return 0;
}

NOTE: The third example overwrites the whole device table by foo::device. Since foo::device does not have port member variable, file["device"] = f; removes port value in toml table.

thanks, it will be more convenient if i can do it in my way.