Opened 11 years ago
Closed 10 years ago
#6331 closed Bugs (fixed)
[Boost.Test] g++ compilation error due to ambiguity between template<class Cond, class T> struct boost::enable_if and class boost::unit_test::decorator::enable_if as well as the disable_if counterparts introduced after Boost 1.48.0 (up to at least svn rev. 76217)
Reported by: | Owned by: | Gennadiy Rozental | |
---|---|---|---|
Milestone: | To Be Determined | Component: | test |
Version: | Boost Development Trunk | Severity: | Regression |
Keywords: | enable_if, disable_if | Cc: | Gennadiy Rozental vexocide@… bugs@… |
Description
The attached test case exposes a compilation problem with g++ (not clang++) against Boost trunk svn rev. <=76217 (after 1.48.0 release) due to an ambiguity between [[[template<class Cond, class T> struct boost::enable_if}}} and class boost::unit_test::decorator::enable_if
in boost/typeof/native.hpp
, as well as the disable_if counterparts.
The test case compiles correctly against Boost 1.48.0 using Apple g++ 4.2.1, MacPorts g++ 4.5.3 and 4.6.2 as well as Apple clang++ 3.0 on Mac OS X Lion 10.7.2 and Xcode 4.2.1. It fails to compile against Boost trunk until at least svn rev. 76217 using any of the mentioned g++ versions. Surprisingly, clang++ 3.0 is still able to correctly compile the test case.
The test case is derived from test_signed_integer_output_with_karma.cpp in Trac ticket #6126. During the discussion of ticket #6126 on the Boost-Spirit-general mailing list, Jeroen Habraken identified the header boost/test/tree/decorator.hpp
as the origin for the compilation failure of the test case against Boost trunk. He found the cause to be an ambiguity:
$ g++-mp-4.6 -o test_boost_test_decorator_enable_if test_boost_test_decorator_enable_if.cpp -I.../boost-trunk In file included from test_boost_test_decorator_enable_if.cpp:58:0: boost/typeof/native.hpp:30:18: error: expected nested-name-specifier before 'enable_if' boost/typeof/native.hpp:30:27: error: expected initializer before '<' token boost/typeof/native.hpp:34:18: error: expected nested-name-specifier before 'disable_if' boost/typeof/native.hpp:34:28: error: expected initializer before '<' token
These occur because the code states "typename enable_if<Cond, T>::type
" and the type name
doesn't make sense in combination with
boost::unit_test::decorator::enable_if
. When removing the typename
, on gets the following
ambiguity error:
boost/typeof/native.hpp:30:9: error: reference to 'enable_if' is ambiguous boost/utility/enable_if.hpp:36:10: error: candidates are: template<class Cond, class T> struct boost::enable_if boost/test/tree/decorator.hpp:184:23: error: class boost::unit_test::decorator::enable_if
showing the conflict between template<class Cond, class T> struct boost::enable_if
and class boost::unit_test::decorator::enable_if
.
As enable_if
is often used without being fully qualified this breaks in a major fashion. Since boost/test/tree/decorator.hpp
seems to be quite new (added 2011-10-02 11:00:16 +0200) it might be best fixed there.
My search on trac for boost::unit_test::decorator_enable_if
turned up changeset 74663 by rogeeff, who I therefore put in CC.
Attachments (2)
Change History (12)
by , 11 years ago
Attachment: | test_boost_test_decorator_enable_if.cpp added |
---|
comment:1 by , 11 years ago
Keywords: | disable_if added |
---|
comment:2 by , 11 years ago
Severity: | Problem → Regression |
---|
follow-up: 4 comment:3 by , 11 years ago
- I am yet to see why this is boost.test fault and not compiler bug.
- I think qualifying symbols from boost namespace is right thing to
do in any case
- This code is not part of the release.
Gennadiy
comment:4 by , 11 years ago
Replying to rogeeff@…:
- I am yet to see why this is boost.test fault and not compiler bug.
It might well be a compiler bug, but seeing how long it takes that new compiler versions are widely deployed even on common platforms such as Windows, Linux, or Mac OS X -- especially in production environments, such issues should be fixed also in the Boost library.
That said, before simply blaming the compiler, we should also make sure that it is not some bug in Boost.Test or other Boost component.
The test case just includes two Boost headers and then fails to compile with g++ 4.2.1, 4.5.3, and 4.6.2 (clang+ + 3.0 compiles just fine the test case):
#define BOOST_TEST_MODULE test_boost_test_decorator_enable_if #include <boost/test/included/unit_test.hpp> #include <boost/typeof/native.hpp> BOOST_AUTO_TEST_CASE(test_dummy) { // do nothing }
I'm not familiar enough with all the magic going on behind the scenes in
Boost.Test to judge if it not changes the visibility of certain symbols
in certain namespaces, e.g., by issuing using
statements.
At least, just including into a test case:
#include <boost/test/tree/decorator.hpp> #include <boost/typeof/native.hpp> int main(int argc, char* argv[]) { return 0; }
won't cause a compiler error. I don't know what triggers the compiler to
look-up enable_if<Cond, T>
in the other test case.
I don't know either why the compiler sees the definition of
boost::unit_test::decorator::enable_if
in namespace boost::type_of
.
I don't know how to further analyse the issue.
- I think qualifying symbols from boost namespace is right thing to do in any case
Well, I agree, but what is a user of the Boost libraries able to do about
it? Using enable_if
and co. without a qualifying namespace is widespread
in the Boost sources: A grep on the Boost headers and some filtering
shows that enable_if
without a qualifying namespace identifier is used
approx. 1000 times all over the Boost library. Therefore, I can imaging that qualifying all occurences
of enable_if
and co. will need a quite huge and well coordinated effort
to be fixed by the different library authors.
I am aware that also other Boost libraries have their own enable_if
variants. However, all seem to be templates except for the
boost::unit_test::decorator::enable_if
. Maybe therefore no problems were
yet observed in combination with typename
statements. At least that is
how far I understand the issue.
- This code is not part of the release.
This is good to hear. Boost.Test is very useful for me and I use it in conjunction with other Boost libraries regularly. Having it broken in a an official Boost release would cause me quite some headache as suddenly my unit tests for my own code would stop compiling for reasons I cannot influence.
Gennadiy
comment:5 by , 11 years ago
While digging into the issue, I came across the CHANGES document for g++ 4.7.0 currently under development. It states:
"G++ now correctly implements the two-phase lookup rules such that an unqualified name used in a template must have an appropriate declaration found either in scope at the point of definition of the template or by argument-dependent lookup at the point of instantiation. As a result, code that relies on a second unqualified lookup at the point of instantiation to find functions declared after the template or in dependent bases will be rejected. The compiler will suggest ways to fix affected code, and using the -fpermissive compiler flag will allow the code to compile with a warning."
Could this problem be related?
I also found a meta-bug in gcc's bug tracker (ticket #18805) grouping currently known problems around the name-lookup.
comment:6 by , 11 years ago
I just tried to compile the test case with g++ version 4.7.0 20120114 (experimental). It still gives the same errors as the older g++ that I tried previously.
comment:8 by , 11 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Thanks for finding the origin of the issue in a misplaced using namespace boost::unit_test
statement in the implementation of the boost::unit_test! Unfortunately, the change set 76600 doesn't fully resolve the issue. There's another using namespace boost::unit_test
statement hidden in in boost/test/impl/logged_expectations.ipp
. I attach a patch, which finally allows me to compile my test case against Boost trunk.
by , 11 years ago
Attachment: | test_impl_logged_expectations.ipp.patch added |
---|
Patch misplaced using namespace statement in boost/test/impl/logged_expectations.ipp
comment:9 by , 11 years ago
I just checked out Boost trunk rev. 76906. test_impl_logged_expectations.ipp.patch
hasn't been applied to it yet to fix the misplaced using namespace
statement in boost/test/impl/logged_expectations.ipp
.
comment:10 by , 10 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
test case