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

Iterate over nested Tables (Array of Tables) #219

Open
KevDi opened this issue Jan 19, 2024 · 9 comments
Open

Iterate over nested Tables (Array of Tables) #219

KevDi opened this issue Jan 19, 2024 · 9 comments
Assignees
Labels
bug Something isn't working

Comments

@KevDi
Copy link

KevDi commented Jan 19, 2024

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;
}
@KevDi KevDi added the bug Something isn't working label Jan 19, 2024
@marzer
Copy link
Owner

marzer commented Jan 19, 2024

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
Copy link
Author

KevDi commented Jan 19, 2024

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
Copy link

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
Copy link

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.

@N-Dekker
Copy link
Contributor

N-Dekker commented Feb 4, 2025

Hi Kevin, I just encountered the same issue! It appears that the old lambda processor of Visual C++ is buggy. It does not seem to understand some conditional noexcept's in lambda's, for example at:

noexcept(for_each_is_nothrow_one<Func&&, Array&&, decltype(elem)>::value)

noexcept(for_each_is_nothrow_one<Func&&, Table&&, decltype(v)>::value)

You can get an "updated" lambda processor by compiler option /Zc:lambda (or implicitly by /permissive- or /std:c++20): https://learn.microsoft.com/en-us/cpp/build/reference/zc-lambda?view=msvc-170 Does that fix those compile errors for you as well?

It's still a bit cumbersome, of course. @marzer Hi Mark! Would it be an option to allow disabling those conditional noexcept's, for example by a macro like TOML_DISABLE_CONDITIONAL_NOEXCEPT_LAMBDA? Or do you consider those noexcept's essential?

In Visual Studio 2022, the compiler errors can be reproduced by opening "toml++.sln", opening the Properties of one of the projects in "tests" (via Solution Explorer), for example "test_debug_x64", and then manually changing its Language property Conformance mode to Default, or No (/permissive)

@marzer
Copy link
Owner

marzer commented Feb 6, 2025

Or do you consider those noexcept's essential?

No, it's fine if they're disabled. They're only an optimization; removing them just means you lose the noexcept annotation in all cases, instead of only losing it sometimes. Not going to be the end of the world.

@N-Dekker
Copy link
Contributor

N-Dekker commented Feb 6, 2025

Thanks @marzer ! Just out of personal interest, do you expect an observable run-time performance gain from these particular noexcept annotations? (In general, I have seen both positive and negative performance effects from using noexcept, depending on the use case.)

@marzer
Copy link
Owner

marzer commented Feb 6, 2025

Heh, that's a question with no one specific answer, sadly. Even just within the MSVC universe it used to actively be a pessimization to specify noexcept, but then at some point they re-wrote some aspect of their constexpr evaluator and suddenly it was an overt optimization.

I know that these days most compilers will be able to optimize nested inlines better when they can see the "noexceptness" is consistent throughout, but apart from that I mostly see it more as a programmer communication tool - it's quite valuable to be able to say in the code "this only throws when X".

N-Dekker added a commit to N-Dekker/tomlplusplus that referenced this issue Feb 6, 2025
Offered a workaround to compile errors like "error C2057: expected constant expression", when using the "legacy lambda processor" of Visual C++. Such compile errors were reported by Kevin Dick, Jan 19, 2024, at issue marzer#219
@N-Dekker
Copy link
Contributor

N-Dekker commented Feb 6, 2025

N-Dekker added a commit to N-Dekker/tomlplusplus that referenced this issue Feb 7, 2025
Offered a workaround to compile errors like "error C2057: expected constant expression", when using the "legacy lambda processor" of Visual C++. Such compile errors were reported by Kevin Dick, Jan 19, 2024, at issue marzer#219
N-Dekker added a commit to N-Dekker/tomlplusplus that referenced this issue Feb 7, 2025
Offered a workaround to compile errors like "error C2057: expected constant expression", when using the "legacy lambda processor" of Visual C++. Such compile errors were reported by Kevin Dick, Jan 19, 2024, at issue marzer#219
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants