Comments (8)
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.
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.
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.
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.
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.
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.
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.
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)
- How to correctly read into variant where structs have the same member names? HOT 1
- Compilation error because of `glaze/reflection/enum_macro.hpp` HOT 5
- Reading and Writing binary to std::vector fails with `data_must_be_null_terminated` HOT 2
- error_on_unknown_keys does not provide any info about the key in error_ctx HOT 2
- GLZ_FLATTEN adds significant compilation time on MSVC. HOT 3
- error HOT 2
- GLZ_FLATTEN adds significant compilation time on gcc. HOT 12
- host_include -> file_include -> fails parsing with `expected_comma`
- std::array<char> partial read handling HOT 9
- Binary (BEVE) support lacking for object keys HOT 8
- Type selection when reading to a variant HOT 1
- Update to v3.2.2 causes compilation errors HOT 9
- new_lines_in_arrays option should apply to writing JSON and not just prettify_json
- std::pair of structs fails round trip HOT 2
- Any struct with any members named "first" and "second" in any order is treated as a std::pair HOT 4
- can't write enum with the highest value HOT 4
- There seems to be an error. HOT 10
- Possible bug following examples in the README? HOT 1
- _GLIBCXX_DEBUG for libstdc++ cannot currently be used with glaze HOT 1
- Compilation error on 32-bit system HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
š Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ā¤ļø Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from glaze.