Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better c++ #1965

Open
wants to merge 6 commits into
base: stable
Choose a base branch
from
Open

Better c++ #1965

wants to merge 6 commits into from

Conversation

christopherlam
Copy link
Contributor

@christopherlam christopherlam commented Jun 19, 2024

to be selectively merged after 5.7.

  • adds an overloaded gnc_account_foreach_descendant for c++ use.
  • use c++ containers instead of creating new GLists

@christopherlam christopherlam force-pushed the better-c++ branch 6 times, most recently from 447f6b1 to 1e37258 Compare June 24, 2024 10:14
@christopherlam christopherlam force-pushed the better-c++ branch 2 times, most recently from 27f6336 to 95cfcf9 Compare July 2, 2024 12:56
@jralls
Copy link
Member

jralls commented Jul 3, 2024

to be selectively merged after 5.7.

That would be better as multiple PRs. It's ok to make a chain of them, just say in the comments who depends on who.

libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
gnucash/register/ledger-core/split-register-control.cpp Outdated Show resolved Hide resolved
gnucash/gnome/window-reconcile.cpp Outdated Show resolved Hide resolved
libgnucash/engine/Account.cpp Show resolved Hide resolved
libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
libgnucash/engine/AccountP.hpp Outdated Show resolved Hide resolved
gnucash/import-export/import-main-matcher.cpp Outdated Show resolved Hide resolved
@jralls
Copy link
Member

jralls commented Oct 5, 2024

That last commit about centralizing GValue got me to realize that since you're writing C++ here and accessing the KvpFrames directly, there's no need for GValues at all, use KvpFrame::set_path(std::vector<std::string> path, KvpValue* value) and KvpValue* KvpFrame::get_slot(std::vector<std::string> path). To get a particular type for the KvpValue* use value->get<T>() substituting the type you want for T, as in value->get<time64>();. To create a KvpValue you can just construct it from the source variable KvpValue val(the_time);.

Edit: Better yet move them to qofinstance. The whole point of the GValue dodge was to provide a generic interface similar to g_object_[sg]et for C code. It doesn't make sense to have a bunch of set_kvp_foo_path functions wrapping the abstraction. You could go full C++ and do

template <typename T> T
qof_instance_get_path_value(QofInstance* inst, Path path)
{
     auto kvp_value{inst->get_slot(path)};
     return kvp_value->get<T>();
}

template <typename T> void
qof_instance_set_path_value(QofInstance* inst, Path path, T value) 
{
     KvpValue kvp_value(value);
     inst->kvp_data->set_path(path, kvp_value);
}

Then to handle the edit level and marking-dirty in Account.cpp you'd have

template <typename T>
set_slot_from_path(Account* acc, Path path, T value)
 {
      xaccAccountBeginEdit(acc);
      qof_instance_set_path_value(QOF_INSTANCE(acc), path, value);
      mark_account(acc);
      xaccAccountCommitEdit(acc);
}

When calling qof_instance_get_path_value you'll specify the type that you want, e.g.
qof_instance_get_path_value<gnc_numeric>(acc, path);.

@christopherlam
Copy link
Contributor Author

christopherlam commented Oct 6, 2024

That last commit about centralizing GValue got me to realize that since you're writing C++ here and accessing the KvpFrames directly, there's no need for GValues at all, use KvpFrame::set_path(std::vector<std::string> path, KvpValue* value) and KvpValue* KvpFrame::get_slot(std::vector<std::string> path). To get a particular type for the KvpValue* use value->get<T>() substituting the type you want for T, as in value->get<time64>();. To create a KvpValue you can just construct it from the source variable KvpValue val(the_time);.

Edit: Better yet move them to qofinstance. The whole point of the GValue dodge was to provide a generic interface similar to g_object_[sg]et for C code. It doesn't make sense to have a bunch of set_kvp_foo_path functions wrapping the abstraction. You could go full C++ and do

template <typename T> T
qof_instance_get_path_value(QofInstance* inst, Path path)
{
     auto kvp_value{inst->get_slot(path)};
     return kvp_value->get<T>();
}

Not quite because kvp_value may be a nullptr. Also the get_kvp_boolean_path is a polyglot.

Edit: alternatively we could return std::optional<T>

@christopherlam
Copy link
Contributor Author

christopherlam commented Oct 6, 2024

The last issue is the optional<optional<numeric>> which I admit is confusing but I'm not sure where to initialise the balance limits except on the first getter call.

@christopherlam christopherlam force-pushed the better-c++ branch 4 times, most recently from d8230e3 to 563c974 Compare October 10, 2024 12:47
@jralls
Copy link
Member

jralls commented Oct 11, 2024

If you're going to bury the template declaration in a cpp file, which speeds up compilation especially when rebuilding and avoids ODR problems if the template gets used with the same args in more than one compilation unit, then you have to force instantiation in the cpp file for all of the types you want to use it with. That's just some simple declarations, see gnc-options.cpp for examples.

Copy link
Member

@jralls jralls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note these are overloaded functions returning type T instead of
getting/setting GValues

That's unclear. They're template overrides with std::optional replacing the GValue containing T.

This is pretty close, just a few tweaks left.

libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
@christopherlam christopherlam force-pushed the better-c++ branch 2 times, most recently from 7a2b391 to 066d271 Compare October 12, 2024 03:47
if last-num is empty-string, remove the slot. this makes the behaviour
consistent with other slots.
Copy link
Member

@jralls jralls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still want the QofInstance* NULL check in qof_instance_get_path_kvp and get_kvp_gnc_foo_path removed.

You made a typo in your last commit that causes tests to fail.

@christopherlam
Copy link
Contributor Author

if the last two are ok I'll tidy up and merge in.

Copy link
Member

@jralls jralls left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite, you went in the opposite direction I had in mind. The null/wrong type check needs to be at the lowest level to protect against some future use that doesn't do it. There's no harm in doing it also nearer the source to make a more usefult tracefile.

libgnucash/engine/qofinstance.cpp Show resolved Hide resolved
libgnucash/engine/qofinstance.cpp Show resolved Hide resolved
libgnucash/engine/Account.cpp Outdated Show resolved Hide resolved
these overloaded functions to kvp slots do not require GValue
which do not require GValue dance

small modification of xaccAccountSetLastNum behaviour with
empty-string last_num
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants