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

Using in conjunction with Qt #120

Closed
EosPengwern opened this issue Feb 26, 2021 · 10 comments · Fixed by #303
Closed

Using in conjunction with Qt #120

EosPengwern opened this issue Feb 26, 2021 · 10 comments · Fixed by #303

Comments

@EosPengwern
Copy link

If I #include a Qt header (specifically, the one I tried was <QFileDialog>) before including ryml.hpp, I get a compilation error:

(test.cpp - an otherwise empty file):

#include <QFileDialog>
#include <ryml.hpp>

gives me on Linux (Qt 5.15.2 with gcc 8.1):

In file included from rapidyaml/src/./c4/yml/yml.hpp:6,
                 from rapidyaml/src/ryml.hpp:4,
                 from _TestPropertiesWidget.cpp:19:
rapidyaml/src/./c4/yml/./emit.hpp:63:27: error: expected ‘)’ before ‘type’
     substr emit(EmitType_e type, Tree const& t, size_t id, bool error_on_excess);
                ~          ^~~~~
                           )
rapidyaml/src/./c4/yml/./emit.hpp:65:27: error: expected ‘)’ before ‘type’
     substr emit(EmitType_e type, Tree const& t, bool error_on_excess=true) { return emit(type, t, t.root_id(), error_on_excess); }
                ~          ^~~~~
                           )
In file included from rapidyaml/src/./c4/yml/yml.hpp:6,
                 from rapidyaml/src/ryml.hpp:4,
                 from _TestPropertiesWidget.cpp:19:
rapidyaml/src/./c4/yml/./emit.hpp:67:27: error: expected ‘)’ before ‘type’
     substr emit(EmitType_e type, NodeRef const& n, bool error_on_excess=true) { return emit(type, *n.tree(), n.id(), error_on_excess); }
                ~          ^~~~~
                           )
rapidyaml/src/./c4/yml/./emit.hpp:109:24: error: expected ‘)’ before ‘const’
 inline size_t emit(Tree const& t, size_t id, FILE *f)
                   ~    ^~~~~~
                        )
rapidyaml/src/./c4/yml/./emit.hpp: In function ‘size_t c4::yml::emit_json(const c4::yml::Tree&, size_t, FILE*)’:
rapidyaml/src/./c4/yml/./emit.hpp:120:25: error: expected unqualified-id before ‘(’ token
     size_t len = em.emit(JSON, t, id, /*error_on_excess*/true).len;
                         ^
rapidyaml/src/./c4/yml/./emit.hpp: At global scope:
rapidyaml/src/./c4/yml/./emit.hpp:127:24: error: expected ‘)’ before ‘const’
 inline size_t emit(Tree const& t, FILE *f=nullptr)
                   ~    ^~~~~~
                        )
rapidyaml/src/./c4/yml/./emit.hpp:142:27: error: expected ‘)’ before ‘const’
 inline size_t emit(NodeRef const& r, FILE *f=nullptr)
                   ~       ^~~~~~
                           )
rapidyaml/src/./c4/yml/./emit.hpp: In function ‘OStream& c4::yml::operator<<(OStream&, const c4::yml::Tree&)’:
rapidyaml/src/./c4/yml/./emit.hpp:162:12: error: expected unqualified-id before ‘(’ token
     em.emit(YAML, t.rootref());
            ^
rapidyaml/src/./c4/yml/./emit.hpp: In function ‘OStream& c4::yml::operator<<(OStream&, const c4::yml::NodeRef&)’:
rapidyaml/src/./c4/yml/./emit.hpp:172:12: error: expected unqualified-id before ‘(’ token
     em.emit(YAML, n);
            ^
rapidyaml/src/./c4/yml/./emit.hpp: In function ‘OStream& c4::yml::operator<<(OStream&, const c4::yml::as_json&)’:
rapidyaml/src/./c4/yml/./emit.hpp:181:12: error: expected unqualified-id before ‘(’ token
     em.emit(JSON, *js.tree, js.node);
            ^
rapidyaml/src/./c4/yml/./emit.hpp: At global scope:
rapidyaml/src/./c4/yml/./emit.hpp:191:24: error: expected ‘)’ before ‘const’
 inline substr emit(Tree const& t, size_t id, substr buf, bool error_on_excess=true)
                   ~    ^~~~~~
                        )
rapidyaml/src/./c4/yml/./emit.hpp: In function ‘c4::substr c4::yml::emit_json(const c4::yml::Tree&, size_t, c4::substr, bool)’:
rapidyaml/src/./c4/yml/./emit.hpp:203:28: error: expected unqualified-id before ‘(’ token
     substr result = em.emit(JSON, t, id, error_on_excess);
                            ^
rapidyaml/src/./c4/yml/./emit.hpp: At global scope:
rapidyaml/src/./c4/yml/./emit.hpp:210:24: error: expected ‘)’ before ‘const’
 inline substr emit(Tree const& t, substr buf, bool error_on_excess=true)
                   ~    ^~~~~~
                        )
rapidyaml/src/./c4/yml/./emit.hpp:226:27: error: expected ‘)’ before ‘const’
 inline substr emit(NodeRef const& r, substr buf, bool error_on_excess=true)
                   ~       ^~~~~~
                           )
In file included from rapidyaml/src/./c4/yml/./emit.hpp:363,
                 from rapidyaml/src/./c4/yml/yml.hpp:6,
                 from rapidyaml/src/ryml.hpp:4,
                 from _TestPropertiesWidget.cpp:19:
rapidyaml/src/./c4/yml/././emit.def.hpp:13:29: error: expected unqualified-id before ‘(’ token
 substr Emitter<Writer>::emit(EmitType_e type, Tree const& t, size_t id, bool error_on_excess)
                             ^

and on Windows (with the same version of Qt and VS2019):

emit.hpp(63,28): error C2146: syntax error: missing ')' before identifier 'type'
emit.hpp(100): message : see reference to class template instantiation 'c4::yml::Emitter<Writer>' being compiled
emit.hpp(63,1): error C3646: 'type': unknown override specifier
emit.hpp(63,39): error C2143: syntax error: missing ';' before 'const'
emit.hpp(63,1): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
emit.hpp(63,1): error C3646: 'id': unknown override specifier
emit.hpp(63,60): error C2062: type 'bool' unexpected
emit.hpp(65,28): error C2146: syntax error: missing ')' before identifier 'type'
emit.hpp(65,1): error C3646: 'type': unknown override specifier
emit.hpp(65,17): error C2086: 'c4::substr c4::yml::Emitter<Writer>::EmitType_e': redefinition
emit.hpp(63): message : see declaration of 'c4::yml::Emitter<Writer>::EmitType_e'
emit.hpp(65,39): error C2143: syntax error: missing ';' before 'const'
emit.hpp(65,34): error C2086: 'c4::substr c4::yml::Emitter<Writer>::Tree': redefinition
emit.hpp(63): message : see declaration of 'c4::yml::Emitter<Writer>::Tree'
emit.hpp(65,1): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
emit.hpp(65,46): error C2086: 'const int &c4::yml::Emitter<Writer>::t': redefinition
emit.hpp(63): message : see declaration of 'c4::yml::Emitter<Writer>::t'

...and many more in a similar vein. If I simply swap around the order of the two includes, putting ryml.hpp first, then everything works fine, on both platforms.

@biojppm
Copy link
Owner

biojppm commented Jun 27, 2021

@EosPengwern thanks for reporting, and sorry for the very late reply.

The QFileDialog header is leaking a define with the very common name emit. This then causes a parse error in the ryml methods named emit().

You can verify the above by doing this:

#include <QFileDialog>
#ifdef emit
#error "qt is leaking emit"
#endif

Or you can do a workaround like this:

#include <QFileDialog>
#undef emit
#include <ryml.hpp>

HTH! I'm closing as the problem comes from Qt and not ryml.

@biojppm biojppm closed this as completed Jun 27, 2021
@VioletGiraffe
Copy link

VioletGiraffe commented Apr 24, 2022

I think it is a problem of ryml that the library is incompatible with a very popular C++ framework. The bigger library wins, and their define is older :)

@biojppm biojppm reopened this Apr 24, 2022
@VioletGiraffe
Copy link

Thanks for reopening the issue and considering my request to look into it. At the very least, may I suggest including this caveat and the solution (#undef) into README?

@biojppm
Copy link
Owner

biojppm commented Apr 25, 2022

You made a sound argument. I plan on adding a #pragma compile-time warning to ryml to let the user know about this. I don't see anything else that can be done to reliably work around the naming conflict.

@VioletGiraffe
Copy link

That is a great idea, it didn't occur to me! The only other solution is to rename emit to something else.

@kdidkovsky
Copy link

kdidkovsky commented Sep 7, 2022

I've found a workaround for this problem. I've written:

`#undef emit

#include "rapidyaml-0.4.1.hpp"

#define emit`

And the software I'm working on compiles fine with Qt. But I had to limit usage of rapidyaml to a single class so that the problem doesn't emerge anywhere else. This solution wont'be convenient for a software with a wider rapidyaml usage, so method renaming would be very welcome.

@biojppm
Copy link
Owner

biojppm commented Sep 7, 2022

@kdidkovsky if you put all of that into a header (wrapping the include), the limit goes away. Eg, like this:

// myrapidyaml.h
#pragma once // or a plain old #ifdef include guard
#undef emit
#include "rapidyaml-0.4.1.hpp"

Then just use your header everywhere:

// file1.cpp
#include "myrapidyaml.h"

// file2.cpp
#include "myrapidyaml.h"

... and you can do this without any limits on usage. That's easy, no?

To be clear, I will not rename the emit() method. But the #pragma warning and the note in the README are due, and that is why this issue is still open.

@VioletGiraffe
Copy link

VioletGiraffe commented Sep 7, 2022

That's workable, but annoying to have to do. I would, of course, not rename the emit method - it's needed for compatibility, but I would add an alternative name for it. E. g. define a new method build or create or write - whatever fits semantically, give this method the implementation of emit, and make emit a wrapper for the new method. That way people who use Qt can call the new alternative method and not encounter the hassle, and the existing code base can keep using emit.

@biojppm
Copy link
Owner

biojppm commented Sep 8, 2022

This problem has been bothering me, because there's really no optimal solution.

With the view of long term comfort, I've reconsidered, and decided to deprecate emit() and emitrs() in favour of emit_yaml() and emitrs_yaml(). This also has the advantage of improved symmetry with emit_json() and emitrs_json(). PR follows.

@yuzu-ogura
Copy link

yuzu-ogura commented Jul 30, 2024

This problem has been bothering me, because there's really no optimal solution.

With the view of long term comfort, I've reconsidered, and decided to deprecate emit() and emitrs() in favour of emit_yaml() and emitrs_yaml(). This also has the advantage of improved symmetry with emit_json() and emitrs_json(). PR follows.

so, is it successful to compile ryml in QT now?
I also met this problem

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 a pull request may close this issue.

5 participants