[Boost-users] conflicting intmax_t definitions - Boost 1.53 and gcc 4.8 incompatibility?

109 views
Skip to first unread message

Nate Finch

unread,
Jan 19, 2014, 9:30:11 AM1/19/14
to boost...@lists.boost.org
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-53-and-gcc-4-8-incompatibility-tp4658121.html
Sent from the Boost - Users mailing list archive at Nabble.com.
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

John Maddock

unread,
Jan 19, 2014, 11:03:46 AM1/19/14
to boost...@lists.boost.org

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.

Nate Finch

unread,
Jan 20, 2014, 7:32:51 AM1/20/14
to boost...@lists.boost.org
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?

John Maddock

unread,
Jan 20, 2014, 8:21:55 AM1/20/14
to boost...@lists.boost.org
>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.

Gavin Lambert

unread,
Jan 20, 2014, 8:23:31 PM1/20/14
to boost...@lists.boost.org
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.

Paul A. Bristow

unread,
Jan 21, 2014, 5:24:47 AM1/21/14
to boost...@lists.boost.org


> -----Original Message-----
> From: Boost-users [mailto:boost-use...@lists.boost.org] On Behalf Of Gavin Lambert
> Sent: Tuesday, January 21, 2014 1:24 AM
> To: boost...@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
pbri...@hetp.u-net.com

John M. Dlugosz

unread,
Jan 21, 2014, 10:20:32 AM1/21/14
to boost...@lists.boost.org
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).

Leon Mlakar

unread,
Jan 21, 2014, 10:27:38 AM1/21/14
to boost...@lists.boost.org
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

Nate Finch

unread,
Jan 21, 2014, 2:16:16 PM1/21/14
to boost...@lists.boost.org
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.

Nate Finch

unread,
Jan 21, 2014, 2:23:50 PM1/21/14
to boost...@lists.boost.org
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.

Gavin Lambert

unread,
Jan 21, 2014, 5:31:57 PM1/21/14
to boost...@lists.boost.org
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).

Vicente J. Botet Escriba

unread,
Jan 21, 2014, 6:30:05 PM1/21/14
to boost...@lists.boost.org
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

Nevin Liber

unread,
Jan 21, 2014, 6:31:59 PM1/21/14
to Renee Silverman
On 21 January 2014 16:31, Gavin Lambert <gav...@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).

Leon Mlakar

unread,
Jan 21, 2014, 6:44:33 PM1/21/14
to boost...@lists.boost.org
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

Gavin Lambert

unread,
Jan 21, 2014, 7:45:57 PM1/21/14
to boost...@lists.boost.org
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.

Gavin Lambert

unread,
Jan 21, 2014, 8:01:05 PM1/21/14
to boost...@lists.boost.org
On 22/01/2014 12:31, Quoth Nevin Liber:
> On 21 January 2014 16:31, Gavin Lambert <gav...@compacsort.com
> <mailto:gav...@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-and-stdshared-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.)

John M. Dlugosz

unread,
Jan 26, 2014, 8:51:21 PM1/26/14
to boost...@lists.boost.org
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".

John M. Dlugosz

unread,
Jan 26, 2014, 9:01:48 PM1/26/14
to boost...@lists.boost.org
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

John M. Dlugosz

unread,
Jan 26, 2014, 9:08:29 PM1/26/14
to boost...@lists.boost.org
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

John M. Dlugosz

unread,
Jan 28, 2014, 9:40:09 PM1/28/14
to boost...@lists.boost.org
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.

Nevin Liber

unread,
Apr 9, 2014, 5:37:56 PM4/9/14
to Renee Silverman
On 20 January 2014 07:21, John Maddock <jo...@johnmaddock.co.uk> 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?

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 :-)
Reply all
Reply to author
Forward
0 new messages