Giter Club home page Giter Club logo

Comments (8)

shiretu avatar shiretu commented on August 27, 2024
void parse(auto&& data) {
    const auto doJsonParse=[](auto&& data){
        struct {
            int field1;
            int field2;
        } parsed;
        glz::context ctx{};
        const auto err = glz::read<glz::opts{.error_on_unknown_keys = false}>(parsed, data, ctx);
        if (err)
                ....
    };
    return doJsonParse(data);
}

The secret sauce is anonymous structs inside local lambdas.

It works with clang tho. Gcc chokes on something.

If I just make that struct global and named (move it out), it works.

The inner lambda creation and usage looks wonky in the sample above, but it has its purpose in the real production code. I have just extracted the essence of the use case.

But it then kinda breaks encapsulation. Exterior world should not be aware of my holding container-like struct

from glaze.

stephenberry avatar stephenberry commented on August 27, 2024

I just added a bit more clarification to the README, but Glaze aims to support the latest three versions of GCC and Clang, and the latest version of MSVC and Apple Clang. This allows Glaze to improve at pace with C++ language improvements.

This means that GCC 11 support is not being maintained anymore, and we're just focusing on GCC 12, 13, & 14. If you find compilation errors in these versions, please report them. Thanks for bringing up these issues and helping this library!

from glaze.

shiretu avatar shiretu commented on August 27, 2024

I'm afraid that's not really accurate. Just got the same error again, this time with the latest compiler supported by MacOS, the one that comes with XCode:

Here is the sample app:

#include <iostream>

int main(void) {
  {
    struct S {
      int a;
      int b;
      glz::raw_json c;
    };
    static constexpr std::string_view raw = R"({"a":1,"b":2,"c":{}})";

    S s;
    const auto err = glz::read_json(s, raw);
    std::cerr << "err: " << static_cast<int>(err.ec) << "\n";
  }
}

and here is the output:

[main] Building folder: glaze 
[build] Starting build
[proc] Executing command: /opt/homebrew/bin/cmake --build /Users/shiretu/work/glaze/build --config Debug --target all --
[build] [1/2  50% :: 0.816] Building CXX object CMakeFiles/test.dir/main.cpp.o
[build] FAILED: CMakeFiles/test.dir/main.cpp.o 
[build] /Library/Developer/CommandLineTools/usr/bin/c++  -isystem /Users/shiretu/work/glaze/build/_deps/glaze-src/include -g -std=gnu++20 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -Wno-missing-braces -MD -MT CMakeFiles/test.dir/main.cpp.o -MF CMakeFiles/test.dir/main.cpp.o.d -o CMakeFiles/test.dir/main.cpp.o -c /Users/shiretu/work/glaze/main.cpp
[build] In file included from /Users/shiretu/work/glaze/main.cpp:1:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/glaze.hpp:35:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary.hpp:6:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary/custom.hpp:6:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary/read.hpp:7:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary/skip.hpp:8:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/core/read.hpp:8:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/api/std/span.hpp:8:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/api/hash.hpp:9:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/core/meta.hpp:8:
[build] /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/reflection/get_name.hpp:23:19: error: variable 'glz::detail::external<S>' is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkage
[build]    extern const T external;
[build]                   ^
[build] /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/reflection/get_name.hpp:44:71: note: used here
[build]    constexpr std::string_view get_name_impl = mangled_name<get_ptr<N>(external<std::remove_volatile_t<T>>)>();
[build]                                                                       ^
[build] 1 error generated.
[build] ninja: build stopped: subcommand failed.
[proc] The command: /opt/homebrew/bin/cmake --build /Users/shiretu/work/glaze/build --config Debug --target all -- exited with code: 1
[driver] Build completed: 00:00:00.836
[build] Build finished with exit code 1

from glaze.

shiretu avatar shiretu commented on August 27, 2024

It seems that it really does not like scopes at all. Scopes are essential for not starting to invent weird names, severe cases of 8+ namespaces, etc. Ideally, it would be nice to declare the struct needed right there, in the function which handles the JSON, without the need to be visible outside of it

from glaze.

shiretu avatar shiretu commented on August 27, 2024

actually, that code above fails under clang-18 as well:

[main] Building folder: glaze 
[build] Starting build
[proc] Executing command: /opt/homebrew/bin/cmake --build /Users/shiretu/work/glaze/build --config Debug --target all --
[build] [1/2  50% :: 1.121] Building CXX object CMakeFiles/test.dir/main.cpp.o
[build] FAILED: CMakeFiles/test.dir/main.cpp.o 
[build] /opt/homebrew/Cellar/llvm/18.1.6/bin/clang++  -isystem /Users/shiretu/work/glaze/build/_deps/glaze-src/include -g -std=gnu++20 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -Wno-missing-braces -MD -MT CMakeFiles/test.dir/main.cpp.o -MF CMakeFiles/test.dir/main.cpp.o.d -o CMakeFiles/test.dir/main.cpp.o -c /Users/shiretu/work/glaze/main.cpp
[build] In file included from /Users/shiretu/work/glaze/main.cpp:1:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/glaze.hpp:35:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary.hpp:6:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary/custom.hpp:6:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary/read.hpp:7:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/binary/skip.hpp:8:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/core/read.hpp:8:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/api/std/span.hpp:8:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/api/hash.hpp:9:
[build] In file included from /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/core/meta.hpp:8:
[build] /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/reflection/get_name.hpp:23:19: error: variable 'glz::detail::external<S>' is used but not defined in this translation unit, and cannot be defined in any other translation unit because its type does not have linkage
[build]    23 |    extern const T external;
[build]       |                   ^
[build] /Users/shiretu/work/glaze/build/_deps/glaze-src/include/glaze/reflection/get_name.hpp:44:71: note: used here
[build]    44 |    constexpr std::string_view get_name_impl = mangled_name<get_ptr<N>(external<std::remove_volatile_t<T>>)>();
[build]       |                                                                       ^
[build] 1 error generated.
[build] ninja: build stopped: subcommand failed.
[proc] The command: /opt/homebrew/bin/cmake --build /Users/shiretu/work/glaze/build --config Debug --target all -- exited with code: 1
[driver] Build completed: 00:00:01.136
[build] Build finished with exit code 1

from glaze.

stephenberry avatar stephenberry commented on August 27, 2024

This is a limitation of the C++ language.

From cppreference on Static Data Members:

Static data members of a class in namespace scope have external linkage if the class itself has external linkage (is not a member of unnamed namespace). Local classes (classes defined inside functions) and unnamed classes, including member classes of unnamed classes, cannot have static data members.

In order for Glaze to build compile time hash maps and serialization code for your types at compile time, it has to use static memory.

It's a bit easier to understand this issue if you consider how the non-reflection use cases work.

Consider the local metadata approach first:

int main(void) {
    {
        struct S {
            int a;
            int b;
            glz::raw_json c;

            struct glaze {
                using T = S;
                static constexpr auto value = glz::object(&T::a, &T::b, &T::c);
            };
        };
   
        static constexpr std::string_view raw = R"({"a":1,"b":2,"c":{}})";

        S s;
        const auto err = glz::read_json(s, raw);
        std::cerr << "err: " << static_cast<int>(err.ec) << "\n";
    }
}

This won't compile because the value in the glaze struct must be static.

Now if we try an external glz::meta solution:

int main(void) {
    {
        struct S {
            int a;
            int b;
            glz::raw_json c;
        };

        static constexpr std::string_view raw = R"({"a":1,"b":2,"c":{}})";

        S s;
        const auto err = glz::read_json(s, raw);
        std::cerr << "err: " << static_cast<int>(err.ec) << "\n";
    }
}

template <>
struct glz::meta<S> {
    using T = S;
    static constexpr auto value = glz::object(&T::a, &T::b, &T::c);
};

This won't compile because our struct S wasn't declared at this scope and is not reachable.

When Glaze builds code for pure reflected structures it must use a compile time extern value. But, extern cannot be linked with internally scoped structures.

Your use case will probably become possible with C++26 if we get the compile time reflection proposal accepted, but for now the language forbids this working.

I hope this helps to explain the limitation. Thanks for asking!

from glaze.

shiretu avatar shiretu commented on August 27, 2024

Iā€™m not sure I fully understand the internals of glaze, but for sure those scoped structs do not have static member vars.

Furthermore, scoping with lambdas instead of normal blocks seems to work, at least for clang.

Is more like a minor nuisance once the structs are retracted into separate files, and the namespace for them used at the site of parsing.

Best regards,
Andrei

from glaze.

stephenberry avatar stephenberry commented on August 27, 2024

GCC would work if you used the -fpermissive flag, but this is stating that it is beyond the C++ standard. I think that might be why the Clang example with the lambda is working. But, I'm actually not sure how that works.

from glaze.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    šŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. šŸ“ŠšŸ“ˆšŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ā¤ļø Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.