[foreach] use of boost_foreach_argument_dependent_lookup_hack
Hi,
Boost.MultiIndex indices, which are not copyable, interoperate with
Boost.Foreach by defining the following:
template
template
inline boost::mpl::true_* boost_foreach_is_noncopyable( boost::multi_index::detail::sequenced_index *&, boost::foreach::tag) { return 0; } Unfortunately Qt (in some configuration modes, at least), defines a macro foreach to Q_FOREACH, which produces the following problem, even if Boost.Foreach was not intended to be used:
btw, this can easily be workarounded by using push_macro/pop_macro pragmas on the most widely used compilers. i've submitted some pull requests about this for several libraries, but some devs prefer to blame qt for introducing pseudokeywords instead of merging the workarounds
Tim Blechmann
template
inline boost::mpl::true_* boost_foreach_is_noncopyable( boost::multi_index::detail::sequenced_index *&, boost::foreach::tag) { return 0; } Unfortunately Qt (in some configuration modes, at least), defines a macro foreach to Q_FOREACH, which produces the following problem, even if Boost.Foreach was not intended to be used:
btw, this can easily be workarounded by using push_macro/pop_macro pragmas on the most widely used compilers.
I'm rather conversative and prefer a pragma-free workaround: I don't know which exact compiler versions support push_macro etc.
i've submitted some pull requests about this for several libraries, but some devs prefer to blame qt for introducing pseudokeywords instead of merging the workarounds
The problem is that blaming Qt puts the burden on their blameless users... I'm all for workarounds if they're not overkill. Joaquín M López Muñoz Telefónica
template
inline boost::mpl::true_* boost_foreach_is_noncopyable( boost::multi_index::detail::sequenced_index *&, boost::foreach::tag) { return 0; } Unfortunately Qt (in some configuration modes, at least), defines a macro foreach to Q_FOREACH, which produces the following problem, even if Boost.Foreach was not intended to be used:
btw, this can easily be workarounded by using push_macro/pop_macro pragmas on the most widely used compilers.
I'm rather conversative and prefer a pragma-free workaround: I don't know which exact compiler versions support push_macro etc.
https://github.com/boostorg/foreach/pull/4/files it is supported by msvc for ages and by gcc since 4.6 and clang ...
i've submitted some pull requests about this for several libraries, but some devs prefer to blame qt for introducing pseudokeywords instead of merging the workarounds
The problem is that blaming Qt puts the burden on their blameless users... I'm all for workarounds if they're not overkill.
simply blaming qt is much easier than merging a fix :( iirc this fix would be needed by foreach, multiindex and flyweight ... so definitely no overkill that would help a lot of users ...
On 14.07.2015 20:13, Tim Blechmann wrote:
i've submitted some pull requests about this for several libraries, but some devs prefer to blame qt for introducing pseudokeywords instead of merging the workarounds
The problem is that blaming Qt puts the burden on their blameless users... I'm all for workarounds if they're not overkill.
simply blaming qt is much easier than merging a fix :(
iirc this fix would be needed by foreach, multiindex and flyweight ... so definitely no overkill that would help a lot of users ...
I agree that a workaround on our side may seem an easy solution. But in the long term it is a never ending headache. We have a whole winapi submodule for similar reason, and I see Apple macros cause pain here and there from time to time. People just need to learn to stop using such generic macros - the hard way, if needed. I wonder if the problem has been reported to Qt devs and what was the response.
i've submitted some pull requests about this for several libraries, but some devs prefer to blame qt for introducing pseudokeywords instead of merging the workarounds
The problem is that blaming Qt puts the burden on their blameless users... I'm all for workarounds if they're not overkill.
simply blaming qt is much easier than merging a fix :(
iirc this fix would be needed by foreach, multiindex and flyweight ... so definitely no overkill that would help a lot of users ...
I agree that a workaround on our side may seem an easy solution. But in the long term it is a never ending headache. We have a whole winapi submodule for similar reason, and I see Apple macros cause pain here and there from time to time. People just need to learn to stop using such generic macros - the hard way, if needed. I wonder if the problem has been reported to Qt devs and what was the response.
define QT_NO_KEYWORDS. the qt devs are well aware of these issues, but of course this will probably *never* be the default, because they actually care about backwards compatibility of their APIs and this would break zillions of projects. apple's check macro can also be disabled via __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES, but again: it probably won't be defined as default, as it breaks a lot of code, which relies on the check macro to be defined. this includes some of apple's code like coreaudioutils. apple's developers probably care less about API compatibility than qt's devs, though. so 'learing the hard way' simply won't work here. it is a *constant* headache for many developers and a huge waste of time. boost should be robust enough to avoid this kind of errors to happen ... and simply blaming others code won't help, as maybe you are right, but those others may have user code, which depends on these defaults.
On 15.07.2015 05:30, Tim Blechmann wrote:
I agree that a workaround on our side may seem an easy solution. But in the long term it is a never ending headache. We have a whole winapi submodule for similar reason, and I see Apple macros cause pain here and there from time to time. People just need to learn to stop using such generic macros - the hard way, if needed. I wonder if the problem has been reported to Qt devs and what was the response.
define QT_NO_KEYWORDS. the qt devs are well aware of these issues, but of course this will probably *never* be the default, because they actually care about backwards compatibility of their APIs and this would break zillions of projects.
apple's check macro can also be disabled via __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES, but again: it probably won't be defined as default, as it breaks a lot of code, which relies on the check macro to be defined. this includes some of apple's code like coreaudioutils. apple's developers probably care less about API compatibility than qt's devs, though.
so 'learing the hard way' simply won't work here. it is a *constant* headache for many developers and a huge waste of time. boost should be robust enough to avoid this kind of errors to happen ... and simply blaming others code won't help, as maybe you are right, but those others may have user code, which depends on these defaults.
If there are config macros to disable the offending macros then that's the solution. I realize it's difficult for Qt and Apple to turn them on by default but this shouldn't be that hard for their users. And perhaps it should be advertised as the recommended way of working with Qt. Eventually, this should become headache for Qt devs and those who use these macros in API, not for us.
If there are config macros to disable the offending macros then that's the solution. I realize it's difficult for Qt and Apple to turn them on by default but this shouldn't be that hard for their users. And perhaps it should be advertised as the recommended way of working with Qt. Eventually, this should become headache for Qt devs and those who use these macros in API, not for us.
qt cannot change their defaults, as it would change their API. boost can address the default *without* breaking the API. the headache is not for Qt devs, they don't use boost. the headache is for their users. just like, it is not your headache or joaquin's, but the headache of their users. lets please try not to be dogmatic about it, that won't lead anywere. instead we should to work towards a robust solution, which solves real-world problems.
On Wed, Jul 15, 2015 at 7:24 AM, Tim Blechmann
If there are config macros to disable the offending macros then that's the solution. I realize it's difficult for Qt and Apple to turn them on by default but this shouldn't be that hard for their users. And perhaps it should be advertised as the recommended way of working with Qt. Eventually, this should become headache for Qt devs and those who use these macros in API, not for us.
qt cannot change their defaults, as it would change their API. boost can address the default *without* breaking the API.
It looks like changing the tag or namespace name in Boost.Foreach is an API change. I don't think #pragma-based solution is viable because of limited portability and the need to be applied to all dependent libraries as well.
the headache is not for Qt devs, they don't use boost. the headache is for their users. just like, it is not your headache or joaquin's, but the headache of their users.
It becomes Qt devs' problem if users start to complain (to Qt devs).
On 15/07/2015 16:08, Andrey Semashev wrote:
If there are config macros to disable the offending macros then that's the solution. I realize it's difficult for Qt and Apple to turn them on by default but this shouldn't be that hard for their users. And perhaps it should be advertised as the recommended way of working with Qt. Eventually, this should become headache for Qt devs and those who use these macros in API, not for us.
The problem is that if someone has a large existing Qt application that actually uses these macros (ie. the program fails to compile if the macros are disabled), and then Boost comes along and refuses to compile unless the macros are disabled, then it is more likely that the end user will simply not use Boost than that they will change their existing code. Whereas I assume that the goal of a library is to encourage people to use it. Frameworks are bigger than libraries; libraries have to accommodate frameworks, rather than the reverse. And while the user is allowed to decide to globally disable the framework's macros or not, a library is not. (At least not in public headers; it gets a bit more freedom in compiled source, but that's seldom an issue.)
On Wed, Jul 15, 2015 at 7:28 AM, Gavin Lambert
On 15/07/2015 16:08, Andrey Semashev wrote:
If there are config macros to disable the offending macros then that's the solution. I realize it's difficult for Qt and Apple to turn them on by default but this shouldn't be that hard for their users. And perhaps it should be advertised as the recommended way of working with Qt. Eventually, this should become headache for Qt devs and those who use these macros in API, not for us.
The problem is that if someone has a large existing Qt application that actually uses these macros (ie. the program fails to compile if the macros are disabled), and then Boost comes along and refuses to compile unless the macros are disabled, then it is more likely that the end user will simply not use Boost than that they will change their existing code. Whereas I assume that the goal of a library is to encourage people to use it.
Sure, that may be the case. However, I'm still in favor of pushing for the 'proper' fix on the Qt side, especially since Qt on its own is moving towards C++11 and general C++ compliance. If that large Qt application wishes to stay actual, it will have to move on sooner or later. And from the discussion in Tim's PR[1] it doesn't look like a difficult change to me.
Frameworks are bigger than libraries; libraries have to accommodate frameworks, rather than the reverse. And while the user is allowed to decide to globally disable the framework's macros or not, a library is not. (At least not in public headers; it gets a bit more freedom in compiled source, but that's seldom an issue.)
I don't think so. Every library (or framework as a collection of libraries), no matter how big it is, is a participant in the final application. If one library defines a macro that can affect other libraries, then the offender has to be fixed, not the other way around. It may be hard in practice, like with Qt, but this should be the general direction of tackling the problem. Qt offers a way to do this, and IMO, it should be used. [1] https://github.com/boostorg/foreach/pull/4
Tim Blechmann
I'm rather conversative and prefer a pragma-free workaround: I don't know which exact compiler versions support push_macro etc.
Shouldn't you have # undef foreach after # pragma push_macro("foreach") ?
[push_macro] is supported by msvc for ages and by gcc since 4.6 and clang ...
As for GCC, we're still testing 4.4 (http://tinyurl.com/no2q5wh ). Besides, there are other compilers outside the three big ones, so I'm not so convinced about this patch. I think it's fair to declare Boost.Foreach unusable in the presence of "foreach" macros, and we should only strive to be resilient against these for libs that do not depend on Boost.Foreach (as is the case for Boost.MultiIndex, which merely ensures interoperability with it). So far, direct use of boost_foreach_argument_dependent_lookup_hack seems more robust. Joaquín M López Muñoz Telefónica
I'm rather conversative and prefer a pragma-free workaround: I don't know which exact compiler versions support push_macro etc.
Shouldn't you have
# undef foreach
after
# pragma push_macro("foreach")
?
yes. i didn't pursue this further, since boost devs don't seem to care about qt users and i don't want to waste my time to argue with dogmatic people ...
[push_macro] is supported by msvc for ages and by gcc since 4.6 and clang ...
As for GCC, we're still testing 4.4 (http://tinyurl.com/no2q5wh ). Besides, there are other compilers outside the three big ones, so I'm not so convinced about this patch.
of course this is not a general solution, but a pragmatic way to make the codebase more robust, which works for most users.
I think it's fair to declare Boost.Foreach unusable in the presence of "foreach" macros, and we should only strive to be resilient against these for libs that do not depend on Boost.Foreach (as is the case for Boost.MultiIndex, which merely ensures interoperability with it). So far, direct use of boost_foreach_argument_dependent_lookup_hack seems more robust.
it is possible to use boost.foreach and qt in the same codebase. though in times of range-based for, its use is rather limited, anyway ... fwiw, i've been using these pragmas successfully in a shared qt/boost codebase ...
participants (4)
-
Andrey Semashev
-
Gavin Lambert
-
Joaquin M López Muñoz
-
Tim Blechmann