marzer / tomlplusplus

Header-only TOML config file parser and serializer for C++17.
https://marzer.github.io/tomlplusplus/
MIT License
1.47k stars 141 forks source link

Iterate over nested Tables (Array of Tables) #219

Open KevDi opened 5 months ago

KevDi commented 5 months ago

Hello, this is more a question then a real bug but there was no question to select.

I'm currently try to figure out how to iterate over a set of nested Tables. I tried the example from the Docs for the Arrays but this seems not to work, because i got compiler errors.

This is the Code that i tried:

int main() {
    toml::table tbl;
    try {
        tbl = toml::parse_file("config.toml");
        std::cout << tbl["data"] << '\n';
        toml::array* pipes = tbl["data"].as_array();
        pipes->for_each([](auto&& ele) {
            std::cout << ele << '\n';
        });

    } catch (const toml::parse_error& error) {
        std::cout << error << '\n';
    }

    return 0;
}

And these are the errors i got:

error C2338: static_assert failed: 'TOML node visitors must be invocable for at least one of the toml::node specializations: ...
error C3313: 'keep_going': variable cannot have the type 'const void' ...
error C3536: 'keep_going': cannot be used before it is initialized ...

The Toml i used:

[[data]]
name = "Data_One"

[[data]]
name = "Data_two"

With the following Code i was able to iterate over the nested Tables but i wonder if this is the best or recommended way to do it.

int main() {
    toml::table tbl;
    std::vector<Pipeline> pipes;
    try {
        tbl = toml::parse_file("config.toml");
        std::cout << tbl["data"] << '\n';
        auto pipe = tbl["data"].as_array();
        for (auto& ele : *pipe) {
            std::cout << "----\n";
            std::cout << *ele.as_table() << '\n';
            std::cout << "----\n";
        }

    } catch (const toml::parse_error& error) {
        std::cout << error << '\n';
    }

    return 0;
}
marzer commented 5 months ago

Yeah for_each() should work in the way you've tried it in the first example, and it's not immediately clear to me why it's not here. I'll have a look into it a bit later :)

KevDi commented 5 months ago

If it helps this is the complete Error Message i got using the for_each:

C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(954,17): error C2057: expected constant expression [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\
build\LogAndConfig.vcxproj]
  (compiling source file '../src/main.cpp')
  C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(954,17):
  the template instantiation context (the oldest one first) is
        C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\src\main.cpp(24,14):
        see reference to function template instantiation 'toml::v3::array &toml::v3::array::for_each<main::<lambda_e4d6ad6edc31eb5c8cf5907a57f8dd48>>(Func &&) noexcept(false) &' being compiled
          with
          [
              Func=main::<lambda_e4d6ad6edc31eb5c8cf5907a57f8dd48>
          ]
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(1091,4):
        see reference to function template instantiation 'void toml::v3::array::do_for_each<Func,toml::v3::array&>(Func &&,Array) noexcept(false)' being compiled
          with
          [
              Func=main::<lambda_e4d6ad6edc31eb5c8cf5907a57f8dd48>,
              Array=toml::v3::array &
          ]
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(952,7):
        while compiling class template member function 'decltype(auto) toml::v3::node::visit<toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919>>(Func &&) noexcept(<expr>) &'
          with
          [
              Func=toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919>
          ]
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(920,51):
        see reference to variable template 'const bool toml::v3::node::visit_is_nothrow<<lambda_ccdd4f66ad536494777e0a03ec1da919> &&,toml::v3::node &>' being compiled
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(768,44):
        see reference to variable template 'const bool toml::v3::node::visit_is_nothrow_one<<lambda_ccdd4f66ad536494777e0a03ec1da919> &&,toml::v3::node &,toml::v3::table>' being compiled
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(765,49):
        see reference to variable template 'const bool toml::v3::node::can_visit<<lambda_ccdd4f66ad536494777e0a03ec1da919> &&,toml::v3::node &,toml::v3::table>' being compiled
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(735,42):
        see reference to variable template 'const bool is_invocable_v<<lambda_ccdd4f66ad536494777e0a03ec1da919> &&,toml::v3::table &>' being compiled
        C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.38.33130\include\type_traits(1845,38):
        see reference to alias template instantiation 'std::_Decltype_invoke_nonzero<_Callable,Dest&,>' being compiled
          with
          [
              _Callable=toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919> &&,
              Dest=toml::v3::table
          ]
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(1016,1):
        while compiling class template member function 'auto toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919>::operator ()<Dest&>(Dest &) noexcept(<expr>) const'
          with
          [
              Dest=toml::v3::table
          ]

C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: static_assert failed: 'TOML node visitors must be invocable for at least one of the toml::node specializations
: [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\build\LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::table [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\build\LogAnd
Config.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::array [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\build\LogAnd
Config.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<std::string> [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig
\build\LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<int64_t> [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\bui
ld\LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<double> [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\buil
d\LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<bool> [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\build\
LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<toml::date> [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\
build\LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<toml::time> [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndConfig\
build\LogAndConfig.vcxproj]
C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18): error C2338: |   - toml::value<toml::date_time>' [C:\Users\kev\Documents\Unterlagen\Projekte\programming\cpp\_vs\LogAndC
onfig\build\LogAndConfig.vcxproj]
  (compiling source file '../src/main.cpp')
  C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(800,18):
  the template instantiation context (the oldest one first) is
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(952,7):
        see reference to function template instantiation 'decltype(auto) toml::v3::node::visit<toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919>>(Func &&) noexcept &' being compiled
          with
          [
              Func=toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919>
          ]
        C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\node.hpp(922,11):
        see reference to function template instantiation 'decltype(auto) toml::v3::node::do_visit<Func,toml::v3::node&>(Func &&,Node) noexcept' being compiled
          with
          [
              Func=toml::v3::array::do_for_each::<lambda_ccdd4f66ad536494777e0a03ec1da919>,
              Node=toml::v3::node &
          ]

C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(950,27): error C3313: 'keep_going': variable cannot have the type 'const void' [C:\Users\kev\Documents\Unterlagen\Projekte\progr
amming\cpp\_vs\LogAndConfig\build\LogAndConfig.vcxproj]
  (compiling source file '../src/main.cpp')

C:\Users\kev\.conan2\p\tomlp86c984de8935d\p\include\toml++\impl\array.hpp(1018,10): error C3536: 'keep_going': cannot be used before it is initialized [C:\Users\kev\Documents\Unterlagen\Projekte\program
ming\cpp\_vs\LogAndConfig\build\LogAndConfig.vcxproj]
  (compiling source file '../src/main.cpp')
bobfang1992 commented 3 months ago

Is this possibly related to the issue I am experiencing as well? I tried to upgrade pytomlpp to 3.4.0 this morning and I noticed that when building on Windows I see a similar error for for_each here: https://github.com/bobfang1992/pytomlpp/actions/runs/8308298970/job/22738400091 Thanks!

Schroedingers-Cat commented 3 months ago

Having the same issue with MSVC 19.39.33523.0 when using tomlplusplus 3.4.0 via vcpkg:

std::vector<std::string> valueTextsVector;
auto valueTexts = (*parameter)["valueTexts"].as_array();
if (valueTexts)
{
  // visitation with for_each() helps deal with heterogeneous data
  valueTexts->for_each([&valueTextsVector](auto&& valueText)
  {
    if constexpr (toml::is_string<decltype(valueText)>)
      valueTextsVector.push_back(*valueText);
  });
}

Downgrading to v3.3.0 via vcpkg.json fixes the issue:

{
  "dependencies": [
    "tomlplusplus",
  ],
  "overrides": [
    { 
        "name": "tomlplusplus", 
        "version": "3.3.0"
    }
  ]
}

The same CMake project compiles fine when using clang v15 on macOS with v3.4.0 and v3.3.0.

I wonder if this is a regression in tomlplusplus v3.4.0.