Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is boost _N placeholders doing undefined behavior?

77 views
Skip to first unread message

Johannes Schaub (litb)

unread,
Dec 22, 2010, 4:47:04 PM12/22/10
to
It looks to me as if the following header causes undefined behavior when
included multiple times in a program (in different TUs):

#include <boost/bind.hpp>

inline void g(int a) { }
inline void f() {
int n = 0;
boost::bind(&g, _1)(n);
}

Do I misread the Standard? It appears to say that the definition of "f" will
cause undefined behavior by 3.2/5b2, because the name "_1" will refer to
different entities in each definition of f.

boost defines _1 using an unnamed namespace, and phoenix defines _1 using
internal linkage, both yielding to different entities in different
translation units. Will this cause any practical problems with regard to the
inline function? Could a ODR-checking compiler (maybe one with link-time
optimization) give a diagnostic here?

Thanks for all insights!

Balog Pal

unread,
Dec 22, 2010, 6:10:34 PM12/22/10
to
"Johannes Schaub (litb)" <schaub-...@web.de>

>
> #include <boost/bind.hpp>
>
> inline void g(int a) { }
> inline void f() {
> int n = 0;
> boost::bind(&g, _1)(n);
> }
>
> Do I misread the Standard? It appears to say that the definition of "f"
> will
> cause undefined behavior by 3.2/5b2, because the name "_1" will refer to
> different entities in each definition of f.
>
> boost defines _1 using an unnamed namespace, and phoenix defines _1 using
> internal linkage, both yielding to different entities in different

Are you sure? I thought those live in something like
boost::bind::placeholders...


SG

unread,
Dec 23, 2010, 9:17:49 AM12/23/10
to
On 22 Dez., 22:47, Johannes Schaub (litb) wrote:
> It looks to me as if the following header causes undefined behavior when
> included multiple times in a program (in different TUs):
>
> #include <boost/bind.hpp>
>
> inline void g(int a) { }
> inline void f() {
>   int n = 0;
>   boost::bind(&g, _1)(n);
>
> }
>
> Do I misread the Standard? It appears to say that the definition of "f" will
> cause undefined behavior by 3.2/5b2, because the name "_1" will refer to
> different entities in each definition of f.

I agree with your interpretation. I really don't understand why the
Boost develoers put the placeholders into an unnamed namespace or gave
them internal linkage.

Cheers!
SG

Johannes Schaub (litb)

unread,
Dec 23, 2010, 9:55:21 AM12/23/10
to
SG wrote:

Hm they would need to use "extern" declarations otherwise, and a .cpp file
where they define the placeholder. But they need/want to stay header-only.

James Kanze

unread,
Dec 25, 2010, 7:18:24 PM12/25/10
to
On Dec 22, 9:47 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:

> It looks to me as if the following header causes undefined
> behavior when included multiple times in a program (in
> different TUs):

> #include <boost/bind.hpp>

> inline void g(int a) { }
> inline void f() {
> int n = 0;
> boost::bind(&g, _1)(n);
> }

> Do I misread the Standard? It appears to say that the
> definition of "f" will cause undefined behavior by 3.2/5b2,
> because the name "_1" will refer to different entities in each
> definition of f.

If the name _1 resolves to different entities in different
translation units, then it's undefined behavior if you include
this code in more than one translation unit.

Note that this isn't the only case where the problem might pop
up. Consider:

#include <vector>

int const i = 42;
inline void f(std::vector<int>& v)
{
v.push_back(i);
}

Also undefined behavior (because I doesn't have external
linkage).

> boost defines _1 using an unnamed namespace, and phoenix
> defines _1 using internal linkage, both yielding to different
> entities in different translation units. Will this cause any
> practical problems with regard to the inline function? Could a
> ODR-checking compiler (maybe one with link-time optimization)
> give a diagnostic here?

I doubt that it will cause any problems unless the compiler is
specifically doing ODR checking (which no current compiler
does), and perhaps not even then; the compiler authors might
very well decide that ODR checking doesn't have to be perfect,
and e.g. simply compare an MD5 hash of the token sequence.
Still, it is undefined behavior, and it is rather sloppy of
someone like Boost to let it through.

--
James Kanze

0 new messages