conflicting intmax_t definitions - Boost 1.53 and gcc 4.8 incompatibility?
I recently upgraded to Ubuntu Trusty Tehr, and now the C++ project I'm working on won't build. It looks like the stdlib and Boost aren't working nicely together for some reason. A bunch of typedefs are conflicting between the two, below is one of the errors, where intmax_t is getting defined in two places. I'm not sure what changed, but I now have gcc (Ubuntu/Linaro 4.8.2-14ubuntu2) 4.8.2 and boost Version: 1.53.0.0ubuntu2 Here's an example error message: /usr/include/inttypes.h:290:8: error: reference to ‘intmax_t’ is ambiguous extern intmax_t imaxabs (intmax_t __n) __THROW __attribute__ ((__const__)); ^ In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h:9:0, from /usr/include/inttypes.h:27, from src/uint256.h:11, from src/key.h:12, from src/crypter.h:8, from src/keystore.h:8, from src/script.h:14, from src/script.cpp:11: /usr/include/stdint.h:134:19: note: candidates are: typedef long int intmax_t typedef long int intmax_t; ^ In file included from /usr/include/boost/math_fwd.hpp:12:0, from /usr/include/boost/math/common_factor_ct.hpp:13, from /usr/include/boost/variant/variant.hpp:44, from /usr/include/boost/variant.hpp:17, from src/script.h:12, from src/script.cpp:11: /usr/include/boost/cstdint.hpp:306:50: note: typedef boost::long_long_type boost::intmax_t typedef ::boost::long_long_type intmax_t; Any help would be much appreciated. I'm fine with downgrading something, I'm just not sure what to downgrade.... or if there's an actual fix, that's cool too. -- View this message in context: http://boost.2283326.n4.nabble.com/conflicting-intmax-t-definitions-Boost-1-... Sent from the Boost - Users mailing list archive at Nabble.com.
I recently upgraded to Ubuntu Trusty Tehr, and now the C++ project I'm working on won't build.
It looks like the stdlib and Boost aren't working nicely together for some reason. A bunch of typedefs are conflicting between the two, below is one of the errors, where intmax_t is getting defined in two places. I'm not sure what changed, but I now have gcc (Ubuntu/Linaro 4.8.2-14ubuntu2) 4.8.2 and boost Version: 1.53.0.0ubuntu2
Here's an example error message:
/usr/include/inttypes.h:290:8: error: reference to ‘intmax_t’ is ambiguous extern intmax_t imaxabs (intmax_t __n) __THROW __attribute__ ((__const__)); ^ In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h:9:0, from /usr/include/inttypes.h:27, from src/uint256.h:11, from src/key.h:12, from src/crypter.h:8, from src/keystore.h:8, from src/script.h:14, from src/script.cpp:11: /usr/include/stdint.h:134:19: note: candidates are: typedef long int intmax_t typedef long int intmax_t; ^ In file included from /usr/include/boost/math_fwd.hpp:12:0, from /usr/include/boost/math/common_factor_ct.hpp:13, from /usr/include/boost/variant/variant.hpp:44, from /usr/include/boost/variant.hpp:17, from src/script.h:12, from src/script.cpp:11: /usr/include/boost/cstdint.hpp:306:50: note: typedef boost::long_long_type boost::intmax_t typedef ::boost::long_long_type intmax_t;
Any help would be much appreciated. I'm fine with downgrading something, I'm just not sure what to downgrade.... or if there's an actual fix, that's cool too.
The two types are in different namespaces so I'm not sure why the Boost one would be found at all by GCC's headers... maybe you have a "using namespace boost" at global scope and before your #includes are complete? John.
Yes, there are some using namespace boost statements, and some of them are
before some includes... but why would that suddenly break when it was
working before I upgraded? Is boost now defining its own intmax_t (and
other such tings, like uint64_t) where it wasn't before?
On Sun, Jan 19, 2014 at 11:03 AM, John Maddock
I recently upgraded to Ubuntu Trusty Tehr, and now the C++ project I'm
working on won't build.
It looks like the stdlib and Boost aren't working nicely together for some reason. A bunch of typedefs are conflicting between the two, below is one of the errors, where intmax_t is getting defined in two places. I'm not sure what changed, but I now have gcc (Ubuntu/Linaro 4.8.2-14ubuntu2) 4.8.2 and boost Version: 1.53.0.0ubuntu2
Here's an example error message:
/usr/include/inttypes.h:290:8: error: reference to ‘intmax_t’ is ambiguous extern intmax_t imaxabs (intmax_t __n) __THROW __attribute__ ((__const__)); ^ In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h:9:0, from /usr/include/inttypes.h:27, from src/uint256.h:11, from src/key.h:12, from src/crypter.h:8, from src/keystore.h:8, from src/script.h:14, from src/script.cpp:11: /usr/include/stdint.h:134:19: note: candidates are: typedef long int intmax_t typedef long int intmax_t; ^ In file included from /usr/include/boost/math_fwd.hpp:12:0, from /usr/include/boost/math/common_factor_ct.hpp:13, from /usr/include/boost/variant/variant.hpp:44, from /usr/include/boost/variant.hpp:17, from src/script.h:12, from src/script.cpp:11: /usr/include/boost/cstdint.hpp:306:50: note: typedef boost::long_long_type boost::intmax_t typedef ::boost::long_long_type intmax_t;
Any help would be much appreciated. I'm fine with downgrading something, I'm just not sure what to downgrade.... or if there's an actual fix, that's cool too.
The two types are in different namespaces so I'm not sure why the Boost one would be found at all by GCC's headers... maybe you have a "using namespace boost" at global scope and before your #includes are complete?
John. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Yes, there are some using namespace boost statements, and some of them are before some includes... but why would that suddenly break when it was working before I upgraded? Is boost now defining its own intmax_t (and other such tings, like uint64_t) where it wasn't before?
No, nothing in that part of Boost has changed for some time I believe. Boost does define it's own intmax_t etc *in namespace boost*, if you import these into the global namespace then expect things to break, sorry but that's the way it's *always* been. My guess is it worked before because the Boost and std lib versions happened to be identical by chance. John.
On 21/01/2014 02:21, Quoth John Maddock:
Boost does define it's own intmax_t etc *in namespace boost*, if you import these into the global namespace then expect things to break, sorry but that's the way it's *always* been. My guess is it worked before because the Boost and std lib versions happened to be identical by chance.
My rule of thumb is to never ever do a "using namespace" in the global namespace in a header file, or someplace prior to the point after all #includes in a cpp file. (And be wary of doing it even then.) Strategic "using" or even "using namespace" from other namespaces can be useful, though.
-----Original Message----- From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Gavin Lambert Sent: Tuesday, January 21, 2014 1:24 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] conflicting intmax_t definitions - Boost 1.53 and gcc 4.8 incompatibility?
On 21/01/2014 02:21, Quoth John Maddock:
Boost does define it's own intmax_t etc *in namespace boost*, if you import these into the global namespace then expect things to break, sorry but that's the way it's *always* been. My guess is it worked before because the Boost and std lib versions happened to be identical by chance.
My rule of thumb is to never ever do a "using namespace" in the global namespace in a header file, or someplace prior to the point after all #includes in a cpp file. (And be wary of doing it even
then.)
Strategic "using" or even "using namespace" from other namespaces can be useful, though.
+1 You may be able to get away with using namespace std globally, but doing this with Boost namespace (or any other) is asking for trouble. If it's not you, it may be some other unsuspecting and entirely innocent user - who will be even more perplexed than you! Avoid unnecessary program-miles, keep namespace declarations local :-) Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com
Yeah, I don't know what is different, but I was able to at least get myself
working by removing some using statements and manually specifying the boost
namespace where needed. No idea why it was working before and why it's
broken now, though. Not originally my code... we'll see if anyone else
ends up hitting it who has more time to look into it than I do.
Thanks for the help.
On Mon, Jan 20, 2014 at 8:21 AM, John Maddock
Yes, there are some using namespace boost statements, and some of them are
before some includes... but why would that suddenly break when it was working before I upgraded? Is boost now defining its own intmax_t (and other such tings, like uint64_t) where it wasn't before?
No, nothing in that part of Boost has changed for some time I believe.
Boost does define it's own intmax_t etc *in namespace boost*, if you import these into the global namespace then expect things to break, sorry but that's the way it's *always* been. My guess is it worked before because the Boost and std lib versions happened to be identical by chance.
John. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 20 January 2014 07:21, John Maddock
Yes, there are some using namespace boost statements, and some of them are
before some includes... but why would that suddenly break when it was working before I upgraded? Is boost now defining its own intmax_t (and other such tings, like uint64_t) where it wasn't before?
No, nothing in that part of Boost has changed for some time I believe.
It appears the underlying type of boost::uint64_t did change from unsigned long to unsigned long long with the latest Ubuntu release, while std::uint64_t is still an unsigned long. We found this to be the case with gcc 4.7 and Boost 1.51, anyway. Just an FYI, Nevin :-) -- Nevin ":-)" Liber mailto:nevin@eviloverlord.com (847) 691-1404
On 1/20/2014 6:32 AM, Nate Finch wrote:
Yes, there are some using namespace boost statements, and some of them are before some includes... but why would that suddenly break when it was working before I upgraded? Is boost now defining its own intmax_t (and other such tings, like uint64_t) where it wasn't before?
Because that's what 'using directives' ("using namespace XXX;") are for: to break builds by surprise and cause strange compatibility problems. Any change to the XXX namespace will change the symbols seen by the importer, and that may cause ambiguities (if you're lucky -- they are caught by the compiler) or unintended bizarre calls of the wrong function you didn't even know about (esp. when templates are involved). Don't dump somebody else's namespace into your work willy-nilly. If they are not maintained together, it's just wrong. Use using declarations for individual symbols, declaring just the ones you need (and are thus aware of).
On 21/01/14 16:20, John M. Dlugosz wrote:
On 1/20/2014 6:32 AM, Nate Finch wrote:
Yes, there are some using namespace boost statements, and some of them are before some includes... but why would that suddenly break when it was working before I upgraded? Is boost now defining its own intmax_t (and other such tings, like uint64_t) where it wasn't before?
Because that's what 'using directives' ("using namespace XXX;") are for: to break builds by surprise and cause strange compatibility problems.
Any change to the XXX namespace will change the symbols seen by the importer, and that may cause ambiguities (if you're lucky -- they are caught by the compiler) or unintended bizarre calls of the wrong function you didn't even know about (esp. when templates are involved).
Don't dump somebody else's namespace into your work willy-nilly. If they are not maintained together, it's just wrong. Use using declarations for individual symbols, declaring just the ones you need (and are thus aware of).
Or alternatively avoid using "using" and use fully qualified names (e.g. boost::intmax_t) - there's nothing wrong with this, either. Leon
On 22/01/2014 04:27, Quoth Leon Mlakar:
On 21/01/14 16:20, John M. Dlugosz wrote:
Don't dump somebody else's namespace into your work willy-nilly. If they are not maintained together, it's just wrong. Use using declarations for individual symbols, declaring just the ones you need (and are thus aware of).
Or alternatively avoid using "using" and use fully qualified names (e.g. boost::intmax_t) - there's nothing wrong with this, either.
I'm of two minds about this one, actually. This is the path I've usually taken thus far, but I've had a few cases where I've wanted to change my mind about which class was actually being used (eg. to move from boost::x to std::x or vice versa, or a redirector that eg. attaches a custom allocator to STL containers by default, or even a custom reimplementation of something). So far swapping these over requires a Replace in Files. This is kinda good because everything is more explicit and it's more obvious when you're looking at code that is trying to pass a std::shared_ptr to something that accepts a boost::shared_ptr (for example), but such blanket replacements offend my "define things in one place" instincts. I've been wondering if a better strategy might be to explicitly typedef or "using" the versions I want into the global namespace (or an "app" namespace) in a common header and then use those everywhere instead. Though this is fragile against a misplaced "using namespace". Also both of these ideas have interop problems, eg. trying to pass a boost::container::string to a third-party library that's expecting a std::string. Or worse, std::shared_ptr vs. boost::shared_ptr (as AFAIK there is no way to interop these without copying the underlying object, which breaks the semantics).
Le 21/01/14 23:31, Gavin Lambert a écrit :
On 22/01/2014 04:27, Quoth Leon Mlakar:
On 21/01/14 16:20, John M. Dlugosz wrote:
Don't dump somebody else's namespace into your work willy-nilly. If they are not maintained together, it's just wrong. Use using declarations for individual symbols, declaring just the ones you need (and are thus aware of).
Or alternatively avoid using "using" and use fully qualified names (e.g. boost::intmax_t) - there's nothing wrong with this, either.
I'm of two minds about this one, actually. This is the path I've usually taken thus far, but I've had a few cases where I've wanted to change my mind about which class was actually being used (eg. to move from boost::x to std::x or vice versa, or a redirector that eg. attaches a custom allocator to STL containers by default, or even a custom reimplementation of something).
So far swapping these over requires a Replace in Files. This is kinda good because everything is more explicit and it's more obvious when you're looking at code that is trying to pass a std::shared_ptr to something that accepts a boost::shared_ptr (for example), but such blanket replacements offend my "define things in one place" instincts.
I've been wondering if a better strategy might be to explicitly typedef or "using" the versions I want into the global namespace (or an "app" namespace) in a common header and then use those everywhere instead. Though this is fragile against a misplaced "using namespace". Hi,
I think this is the way to go. Import them in your specific "app" namespace.
Also both of these ideas have interop problems, eg. trying to pass a boost::container::string to a third-party library that's expecting a std::string. Or worse, std::shared_ptr vs. boost::shared_ptr (as AFAIK there is no way to interop these without copying the underlying object, which breaks the semantics).
Well, importing them to the global namespace doesn't work better. If you must use a 3pp library that has a std::shared_ptr in the interface you must use a std::shared_ptr on your application at least for this interface and you must not try to hide this in your code. The use of a specific namespace is useful only to move from one implementation to the other internally in a transparent way. Best, Vicente
On 21 January 2014 16:31, Gavin Lambert
Or worse, std::shared_ptr vs. boost::shared_ptr (as AFAIK there is no way to interop these without copying the underlying object, which breaks the semantics).
Well, you *can*, but it's a bit of a hack... < http://stackoverflow.com/questions/12314967/cohabitation-of-boostshared-ptr-...
. -- Nevin ":-)" Liber mailto:nevin@eviloverlord.com (847) 691-1404
On 22/01/2014 12:31, Quoth Nevin Liber:
On 21 January 2014 16:31, Gavin Lambert
mailto:gavinl@compacsort.com> wrote: Or worse, std::shared_ptr vs. boost::shared_ptr (as AFAIK there is no way to interop these without copying the underlying object, which breaks the semantics).
Well, you /can/, but it's a bit of a hack... http://stackoverflow.com/questions/12314967/cohabitation-of-boostshared-ptr-....
I was wondering if something along those sort of lines would work, after I posted that. But that's actually pretty clever. (Of course "clever" is not always a good thing in code.)
On 21/01/14 23:31, Gavin Lambert wrote:
On 22/01/2014 04:27, Quoth Leon Mlakar:
On 21/01/14 16:20, John M. Dlugosz wrote:
Don't dump somebody else's namespace into your work willy-nilly. If they are not maintained together, it's just wrong. Use using declarations for individual symbols, declaring just the ones you need (and are thus aware of).
Or alternatively avoid using "using" and use fully qualified names (e.g. boost::intmax_t) - there's nothing wrong with this, either.
I'm of two minds about this one, actually. This is the path I've usually taken thus far, but I've had a few cases where I've wanted to change my mind about which class was actually being used (eg. to move from boost::x to std::x or vice versa, or a redirector that eg. attaches a custom allocator to STL containers by default, or even a custom reimplementation of something).
So far swapping these over requires a Replace in Files. This is kinda good because everything is more explicit and it's more obvious when you're looking at code that is trying to pass a std::shared_ptr to something that accepts a boost::shared_ptr (for example), but such blanket replacements offend my "define things in one place" instincts.
I've been wondering if a better strategy might be to explicitly typedef or "using" the versions I want into the global namespace (or an "app" namespace) in a common header and then use those everywhere instead. Though this is fragile against a misplaced "using namespace".
For some time now I'm advocating against importing entire namespace via "using namespace" ... I've seen too many defects caused by misplaced directives. Rather I prefer importing specific symbols, or if that is of little benefit, using fully qualified name. Especially these days when, as you pointed out, ambiguities like boost::shared_ptr and std::shared_ptr can cause terrible mess if it's not obvious which one is used, and for these even importing symbols may not be a good idea. But your suggestion it the last paragraph is intriguing if combined with using type aliases and explicit namespace for symbols used in applications - something like mytypes::shared_ptr or appdef::string ... it is just a soft of half-baked idea at the moment, For now I'm still scratching at the surface of C++11, but we did use type aliases in past C# projects, and the C++ seem to have the advantage of allowing aliases for template classes. I'll give this some thought in the future. I really wonder what sorts of patterns will emerge from this. Leon
On 22/01/2014 12:44, Quoth Leon Mlakar:
On 21/01/14 23:31, Gavin Lambert wrote:
I've been wondering if a better strategy might be to explicitly typedef or "using" the versions I want into the global namespace (or an "app" namespace) in a common header and then use those everywhere instead. Though this is fragile against a misplaced "using namespace". [...] But your suggestion it the last paragraph is intriguing if combined with using type aliases and explicit namespace for symbols used in applications - something like mytypes::shared_ptr or appdef::string ... it is just a soft of half-baked idea at the moment, For now I'm still scratching at the surface of C++11, but we did use type aliases in past C# projects, and the C++ seem to have the advantage of allowing aliases for template classes. I'll give this some thought in the future. I really wonder what sorts of patterns will emerge from this.
Yes, one of the reasons why I haven't been using that strategy thus far is that most of the code I work with is still C++03, and lacks the ability to define a "simple" alias for a templated type(*) -- and most of the types I'd want to do this with are templates (containers and smart pointers). (*) I don't consider having to use "select_my_vector<T>::type" sufficiently simple, vs. "my::vector<T>" -- especially when I don't want client code to have to care/change whether this is a typedef or a reimplementation.
On 1/21/2014 4:31 PM, Gavin Lambert wrote:
On 22/01/2014 04:27, Quoth Leon Mlakar:
I've been wondering if a better strategy might be to explicitly typedef or "using" the versions I want into the global namespace (or an "app" namespace) in a common header and then use those everywhere instead. Though this is fragile against a misplaced "using namespace".
I've found that a way to address environment portability problems. In general, is class C being used from the platform's standard library, from Boost, or some tweaked version or in-company version? As a specific example, system_error is standard now, but on Windows the std::system_error is (or was at the time; I don't know about the current Visual Studio) brain-dead, but boost::system::system_error handles Win32 GetLastError codes and HRESULT's. Another platform might have better support for platform-specific errors and would be used in preference to Boost. I don't recall which platform/version did, but in general it _could_ and planning for that (or moving from one version to another later) is a good idea. —John
On 1/21/2014 4:31 PM, Gavin Lambert wrote:
On 22/01/2014 04:27, Quoth Leon Mlakar: worse, std::shared_ptr vs. boost::shared_ptr (as AFAIK there is no way to interop these without copying the underlying object, which breaks the semantics).
Hmm, there might be. Perhaps using a custom deleter with both, which knows about two masters. A forwarder could allow one shared_ptr to wrap another, but that would mean writing the forwarding stub implementation for the abstract interface. If the class is already using PIMPL or letter/envelopes or otherwise already has a forwarding thing already written, that would be a good way to do it. Why can't Boost simply be configured to have boost::shared_ptr be an alias for std::shared_ptr? Maybe it's time to move to using std::shared_ptr and have Boost's implementation only for Boost::TR1 . —John
On 1/21/2014 9:27 AM, Leon Mlakar wrote: > On 21/01/14 16:20, John M. Dlugosz wrote: >> On 1/20/2014 6:32 AM, Nate Finch wrote: > Or alternatively avoid using "using" and use fully qualified names (e.g. boost::intmax_t) > - there's nothing wrong with this, either. > Actually, there are cases where that's not right, when writing templates. In particular, swap(x,y) where x and y are of type T. You need to write it unqualified to have it find swap via argument-dependent lookup, but when T is int it needs to find std::swap. The idiom (as far as I know) is to declare `using std::swap;` in the function body. FWIW, I often like having common things ready for unqualified use in my CPP files, such as `string` and `make_shared`. I find it easier to read, and it keeps the lines shorter so the real expression fits in one single-gaze clump of reading text. For something like boost::intmax_t where the code wants to emphasize which one is being called, qualifying helps with future maintenance. Like most classes use std::shared_ptr but others (e.g. asio) use boost::shared_ptr, so it's awkward when writing the functions that use both of them. In headers, scope-pollution is prohibited (I mean by policy, not by the language). For most coders that means the rule is equivalent to "don't use `using` in headers".
For what it's worth, I agree 100%. It's a problem in many languages have,
and it's constantly a battle to prevent people from taking the "easy" way
out that happens to also be really dangerous in practice.
For what it's worth, it's not my code originally, so I take no
responsibility for how it was written. At least it's a fairly easy thing
to clean up... just remove the using statement and see where the code falls
over during compilation, and insert an explicit namespace.
On Tue, Jan 21, 2014 at 10:20 AM, John M. Dlugosz
On 1/20/2014 6:32 AM, Nate Finch wrote:
Yes, there are some using namespace boost statements, and some of them are before some includes... but why would that suddenly break when it was working before I upgraded? Is boost now defining its own intmax_t (and other such tings, like uint64_t) where it wasn't before?
Because that's what 'using directives' ("using namespace XXX;") are for: to break builds by surprise and cause strange compatibility problems.
Any change to the XXX namespace will change the symbols seen by the importer, and that may cause ambiguities (if you're lucky -- they are caught by the compiler) or unintended bizarre calls of the wrong function you didn't even know about (esp. when templates are involved).
Don't dump somebody else's namespace into your work willy-nilly. If they are not maintained together, it's just wrong. Use using declarations for individual symbols, declaring just the ones you need (and are thus aware of).
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 1/21/2014 1:23 PM, Nate Finch wrote:
At least it's a fairly easy thing to clean up... just remove the using statement and see where the code falls over during compilation, and insert an explicit namespace.
It's only easy when you can _find_ the 'using' directive. It might be hidden in some header file included many levels deep.
participants (8)
-
Gavin Lambert
-
John M. Dlugosz
-
John Maddock
-
Leon Mlakar
-
Nate Finch
-
Nevin Liber
-
Paul A. Bristow
-
Vicente J. Botet Escriba