version conflicts: is there a solution?

Hi Everyone- This has been discussed before (http://thread.gmane.org/gmane.comp.lib.boost.devel/180008), but I think my question is along a slightly different line so I thought I would ask about it. Let's say I want to compile and distribute a library (without the source), and I happen to use some boost header-only libraries as an implementation detail in some of my functions. None of the headers associated with my library include boost headers; it's purely an internal detail. Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined. I realize this isn't a boost-specific problem (it would affect any library of template functions), but I am wondering if there is a boost-specific solution already worked out? Has anyone thought about this? It seems to me that in this case, what would be ideal would be if I could do: #define BOOST_NAMESPACE some_unique_namespace_for_boost #include "boost/algorithm/string.hpp" BOOST_NAMESPACE::shared_ptr<void> x; //or whatever Then I can insure there are no ODR violations and I don't need to bother users of my library with the fact that I used boost at all. Other than the sheer annoyance of having to go through all the boost code to use this macro, is there a strong downside to this approach? Alternatively, I could try: namespace { #include "boost/..." } But I don't know, could this work? Or are there boost headers that rely on fully qualified references like ::boost::algorithm::whatever? I'd appreciate anyone's thoughts on this issue, thanks! -Lewis

I've done this before, the general pattern I've used is #ifndef FOO_NAMESPACE_NAME # define FOO_NAMESPACE_NAME foo #endif #define FOO_BEGIN namespace FOO_NAMESPACE_NAME { #define FOO_END } #define FOO_NAMESPACE_FOO(name) ::FOO_NAMESPACE_NAME::(name) Of course, it would be quite a chore to trawl through all of boost to make this sort of scheme work. However, version numbers could also be concatenated automatically as required. On Wed, Jun 24, 2009 at 12:49 PM, Lewis Hyatt <lhyatt@gmail.com> wrote:
Hi Everyone-
This has been discussed before (http://thread.gmane.org/gmane.comp.lib.boost.devel/180008), but I think my question is along a slightly different line so I thought I would ask about it. Let's say I want to compile and distribute a library (without the source), and I happen to use some boost header-only libraries as an implementation detail in some of my functions. None of the headers associated with my library include boost headers; it's purely an internal detail.
Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined.
I realize this isn't a boost-specific problem (it would affect any library of template functions), but I am wondering if there is a boost-specific solution already worked out? Has anyone thought about this? It seems to me that in this case, what would be ideal would be if I could do:
#define BOOST_NAMESPACE some_unique_namespace_for_boost #include "boost/algorithm/string.hpp" BOOST_NAMESPACE::shared_ptr<void> x; //or whatever
Then I can insure there are no ODR violations and I don't need to bother users of my library with the fact that I used boost at all.
Other than the sheer annoyance of having to go through all the boost code to use this macro, is there a strong downside to this approach?
Alternatively, I could try:
namespace { #include "boost/..." }
But I don't know, could this work? Or are there boost headers that rely on fully qualified references like ::boost::algorithm::whatever?
I'd appreciate anyone's thoughts on this issue, thanks!
-Lewis
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Wednesday 24 June 2009 02:49:12 am Lewis Hyatt wrote:
Hi Everyone-
This has been discussed before (http://thread.gmane.org/gmane.comp.lib.boost.devel/180008), but I think my question is along a slightly different line so I thought I would ask about it. Let's say I want to compile and distribute a library (without the source), and I happen to use some boost header-only libraries as an implementation detail in some of my functions. None of the headers associated with my library include boost headers; it's purely an internal detail.
That makes it a lot simpler. I would go for a solution where you rename the boost namespace in the source you include to something "private" for your lib. Eg namespace mylib_boost { .. But if you include a lot of source you probably want to have a tool for this. Armed with such a tool, updating to new version of boost for your internal use is simply a mater of re-running the tool. Now I am ignoring all other possible issues unrelated to this thread. I have a patch for tools/bcp which does exactly what I think you need as a part of the process bcp is intended for. Bcp is used to copy part of boost with all its dependencies. If you are interested in this approach I will brush some dust off the patch and sync it with trunk for you.
Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined.
Yes - and that is very bad. Much better if you as a lib provider do some extra work to prevent this. Put all your references to boost is in different namespace.
I realize this isn't a boost-specific problem (it would affect any library of template functions), but I am wondering if there is a boost-specific solution already worked out? Has anyone thought about this? It seems to me that in this case, what would be ideal would be if I could do:
#define BOOST_NAMESPACE some_unique_namespace_for_boost #include "boost/algorithm/string.hpp" BOOST_NAMESPACE::shared_ptr<void> x; //or whatever Then I can insure there are no ODR violations and I don't need to bother users of my library with the fact that I used boost at all.
Other than the sheer annoyance of having to go through all the boost code to use this macro, is there a strong downside to this approach?
Alternatively, I could try:
namespace { #include "boost/..." }
Hmm... I have no idea if this is defined how this will work. But it may be worth figuring it out.
But I don't know, could this work? Or are there boost headers that rely on fully qualified references like ::boost::algorithm::whatever?
I'd appreciate anyone's thoughts on this issue, thanks!
Many approaches to a general solutions for these issues would require changes to a lot of boost, code and they do not support all use-cases. One difficult issue which you have avoided is side-by-side headers from multiple boost versions in same translation unit. My bcp patch is an attempt to get around these issues in a general way. As my need back then faded away, I am unsure of how field tested the patch is by others on this list. Some people tried it out. Artyom's script may be a simpler solution for you, but I have not tested it. -- Bjørn

Lewis Hyatt wrote:
Hi Everyone-
This has been discussed before (http://thread.gmane.org/gmane.comp.lib.boost.devel/180008), but I think my question is along a slightly different line so I thought I would ask about it. Let's say I want to compile and distribute a library (without the source), and I happen to use some boost header-only libraries as an implementation detail in some of my functions. None of the headers associated with my library include boost headers; it's purely an internal detail.
Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined.
If you are distributing a library without the source it means that you are distributing a library in object format, whether shared or static. In this case there is no conflict between the Boost header files you are using internally and other uses of Boost since the end-user of your library never sees the internal header files you are using.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 24 June 2009, Edward Diener wrote:
Lewis Hyatt wrote:
Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined.
If you are distributing a library without the source it means that you are distributing a library in object format, whether shared or static. In this case there is no conflict between the Boost header files you are using internally and other uses of Boost since the end-user of your library never sees the internal header files you are using.
Having the definitions separated into different translation units doesn't seem to be enough to prevent ODR violations according to the standard. It gives a list of requirements for multiple definitions in different translation units in section 3.2.5. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpCJ4IACgkQ5vihyNWuA4W0JwCfSSsWjqvXa0BoYSHBYnnSR2GP jqEAnRuqyevInEoOfkgwv7JSh/pTd8mR =zQIn -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Wednesday 24 June 2009, Edward Diener wrote:
Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined. If you are distributing a library without the source it means that you are distributing a library in object format, whether shared or static. In this case there is no conflict between the Boost header files you are using internally and other uses of Boost since the end-user of your
Lewis Hyatt wrote: library never sees the internal header files you are using.
Having the definitions separated into different translation units doesn't seem to be enough to prevent ODR violations according to the standard. It gives a list of requirements for multiple definitions in different translation units in section 3.2.5.
I do not believe the C++ definition of a "translation unit" comes into play when dealing with a library, but rather with header files included within a source file. If the implementation is internal, as the OP suggested, then I would assume that no header files for the implementation are distributed and therefore no ODR violation for that particular situation should occur. Of course there may be conflicts when linking if internal details of a library are exported but that is not something about which the C++ standard says anything AFAIK.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Wednesday 24 June 2009, Edward Diener wrote:
Having the definitions separated into different translation units doesn't seem to be enough to prevent ODR violations according to the standard. It gives a list of requirements for multiple definitions in different translation units in section 3.2.5.
I do not believe the C++ definition of a "translation unit" comes into play when dealing with a library, but rather with header files included within a source file. If the implementation is internal, as the OP suggested, then I would assume that no header files for the implementation are distributed and therefore no ODR violation for that particular situation should occur.
Of course there may be conflicts when linking if internal details of a library are exported but that is not something about which the C++ standard says anything AFAIK.
Can you point to anything in the standard that supports your position? It may be safe to have an internal usage of boost in your compiled library on a particular C++ implementation, but that doesn't say anything about whether or not an ODR violation is happening. ODR violations are something defined by the standard. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpDdAIACgkQ5vihyNWuA4WNugCfQlQGvX6yDOy/23ZQr5JlWFCX Go8AnRL9iIIob6qJ8cPZkVu+FOv3qZhe =rg/a -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Wednesday 24 June 2009, Edward Diener wrote:
Having the definitions separated into different translation units doesn't seem to be enough to prevent ODR violations according to the standard. It gives a list of requirements for multiple definitions in different translation units in section 3.2.5. I do not believe the C++ definition of a "translation unit" comes into play when dealing with a library, but rather with header files included within a source file. If the implementation is internal, as the OP suggested, then I would assume that no header files for the implementation are distributed and therefore no ODR violation for that particular situation should occur.
Of course there may be conflicts when linking if internal details of a library are exported but that is not something about which the C++ standard says anything AFAIK.
Can you point to anything in the standard that supports your position?
Where in the standard do you see any mention of an ODR violation occuring where there are no header files being distributed for inclusion by a source file which would create such a violation ? As I understand the OP, the Boost header files for the internal usage of Boost in the distributed library is not distributed or needed by the end user when using the library. How can something which does not exist for the end-user of a library produce an ODR violation in a translation unit with other header files ?

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 25 June 2009, Edward Diener wrote:
Can you point to anything in the standard that supports your position?
Where in the standard do you see any mention of an ODR violation occuring where there are no header files being distributed for inclusion by a source file which would create such a violation ?
There is the 3rd paragraph of the "one definition rule" section: "Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used." Note they include "user-defined library". -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpDhukACgkQ5vihyNWuA4VhtgCeOet1XlSbFWpwu5IH+Rv7m4Um 4cIAn233VLhH4+9Do0iky3PF2oql7eMY =6y9C -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 25 June 2009, Frank Mori Hess wrote:
On Thursday 25 June 2009, Edward Diener wrote:
Can you point to anything in the standard that supports your position?
Where in the standard do you see any mention of an ODR violation occuring where there are no header files being distributed for inclusion by a source file which would create such a violation ?
There is the 3rd paragraph of the "one definition rule" section:
Err, actually that doesn't apply to header-only stuff. But going back to section I mentioned originally, there is 3.2.5 which covers multiple definitions in different translation units. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkpDiTsACgkQ5vihyNWuA4U4vgCgzYte35HPcd/DtSxOgFUqTycw PqAAnj5ffxZPro7BZqTeRb0jt/09ZYog =Jm2k -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
On Thursday 25 June 2009, Edward Diener wrote:
Can you point to anything in the standard that supports your position? Where in the standard do you see any mention of an ODR violation occuring where there are no header files being distributed for inclusion by a source file which would create such a violation ?
There is the 3rd paragraph of the "one definition rule" section:
"Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used."
Note they include "user-defined library".
I think that in order to see the whole picture you need to explicitly define what a "definition" is. ISO 14882-2003 3.1 paragraphs 1st and 2nd:
A declaration (clause 7) introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.
A declaration is a /definition/ unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification24) (7.5) and neither an initializer nor a function-body, it declares a static data member in a class declaration (9.4), it is a class name declaration (9.1), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), or a using-directive (7.3.4).
Unless your "user-defined library" include headers you can not introduce names into a translation unit. And even if it does include headers the ODR applies only to the stuff you have in that headers and not to the "rest" of the library. It means that unless you have the Boost headers somewhere in the header part of your library there is no way to violate the ODR as it applies to the translation units only. The linkage of compiled translation units is described in a separate section and has its own rules. Described in section "3.5 Program and linkage". While there is something similar to ODR there, see paragraph 9, but I do not think that it will apply to your case, unless you explicitly declare parts of boost as having external linkage thus making them visible to the linker during the linking process.

Ilya Bobir wrote:
Frank Mori Hess wrote:
On Thursday 25 June 2009, Edward Diener wrote:
Can you point to anything in the standard that supports your position? Where in the standard do you see any mention of an ODR violation occuring where there are no header files being distributed for inclusion by a source file which would create such a violation ?
There is the 3rd paragraph of the "one definition rule" section:
"Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used."
Note they include "user-defined library".
I think that in order to see the whole picture you need to explicitly define what a "definition" is. ISO 14882-2003 3.1 paragraphs 1st and 2nd:
A declaration (clause 7) introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.
A declaration is a /definition/ unless it declares a function without specifying the function’s body (8.4), it contains the extern specifier (7.1.1) or a linkage-specification24) (7.5) and neither an initializer nor a function-body, it declares a static data member in a class declaration (9.4), it is a class name declaration (9.1), or it is a typedef declaration (7.1.3), a using-declaration (7.3.3), or a using-directive (7.3.4).
Unless your "user-defined library" include headers you can not introduce names into a translation unit. And even if it does include headers the ODR applies only to the stuff you have in that headers and not to the "rest" of the library. It means that unless you have the Boost headers somewhere in the header part of your library there is no way to violate the ODR as it applies to the translation units only.
The linkage of compiled translation units is described in a separate section and has its own rules. Described in section "3.5 Program and linkage". While there is something similar to ODR there, see paragraph 9, but I do not think that it will apply to your case, unless you explicitly declare parts of boost as having external linkage thus making them visible to the linker during the linking process.
Artyom wrote:
There are many problems and this is not as simple as you think. Because if you have two versions of foo() defined in header files they may be exported and... collide.
Oh, according to ISO 14882-2003 3.5 paragraph 4 all functions, names classes and some other type of names defined in a namespace scope have external linkage by default. It means that you will violate this rule.

Ilya Bobir wrote:
[...] Oh, according to ISO 14882-2003 3.5 paragraph 4 all functions, names classes and some other type of names defined in a namespace scope have external linkage by default. It means that you will violate this rule.
As this is not a ODR, you can probably work around it by just removing all symbols that refer to boost from your library. strip can be used to perform such a task. It seems to accept wildcards, so you may be able to remove all symbols in boost namespace with just one invocation. You only need to figure out the correct wild card as the C++ symbols will be mangled by the compiler in a compiler dependent way. P.S. Sorry for replying to myself for the second time, but it seems to be a workable solution to me.

On Saturday 27 June 2009, Ilya Bobir wrote:
Ilya Bobir wrote:
[...] Oh, according to ISO 14882-2003 3.5 paragraph 4 all functions, names classes and some other type of names defined in a namespace scope have external linkage by default. It means that you will violate this rule.
As this is not a ODR, you can probably work around it by just removing all symbols that refer to boost from your library.
Leaving aside whether or not it is an ODR violation, why do you care more about the ODR than section 3.5? That is, why would it not be okay to work around an ODR violation using implementation-specific measures, but it would be okay to do so for section 3.5? I don't see how using "strip" to remove symbols is relevant to whether the standard considers a name to have external linkage or not (external linkage being something defined by the standard).
strip can be used to perform such a task. It seems to accept wildcards, so you may be able to remove all symbols in boost namespace with just one invocation. You only need to figure out the correct wild card as the C++ symbols will be mangled by the compiler in a compiler dependent way.

On Saturday 27 June 2009 10:17:06 pm Ilya Bobir wrote:
Ilya Bobir wrote:
[...] Oh, according to ISO 14882-2003 3.5 paragraph 4 all functions, names classes and some other type of names defined in a namespace scope have external linkage by default. It means that you will violate this rule.
As this is not a ODR, you can probably work around it by just removing all symbols that refer to boost from your library. strip can be used to perform such a task. It seems to accept wildcards, so you may be able to remove all symbols in boost namespace with just one invocation. You only need to figure out the correct wild card as the C++ symbols will be mangled by the compiler in a compiler dependent way.
Nice. I have never thought of strip as a tool for other things than removing debug info. This can actually be a useful suggestion. -- Bjørn

On Sunday 28 June 2009 11:21:08 am Bjørn Roald wrote:
On Saturday 27 June 2009 10:17:06 pm Ilya Bobir wrote:
As this is not a ODR, you can probably work around it by just removing all symbols that refer to boost from your library. strip can be used to perform such a task. It seems to accept wildcards, so you may be able to remove all symbols in boost namespace with just one invocation. You only need to figure out the correct wild card as the C++ symbols will be mangled by the compiler in a compiler dependent way.
Nice. I have never thought of strip as a tool for other things than removing debug info. This can actually be a useful suggestion.
Sadly it does not work. I just did some testing and on Linux and it seems this will not work, not even for header only boost libs. Ultimately I end up with linking errors ("undefined symbols") or in the case of header only libs strip refuses to cooperate with warnings like this: strip: not stripping symbol `_ZN5boost1A3fooEv' because it is named in a relocation I do not know what is meant by relocation here, but if I interprets this correctly the strip tool does not attempts to remove the symbol purely as a reference to the code. It attempts to remove the code pointed to by the symbol as well. Hence, it refuses to remove symbols that are in use by other code in same translation unit. If anybody is interested, below is listings of what I tested. -- Bjørn bjorn@frodo2:~/src/c++/test$ cat a.hpp namespace boost { class A { public: const char* foo(); }; } bjorn@frodo2:~/src/c++/test$ cat a.cpp #include "a.hpp" namespace { const char astring[] = "aaaaa"; } const char* boost::A::foo() { return "aaaappp";//astring; } bjorn@frodo2:~/src/c++/test$ cat b.hpp namespace mylib { int lib_func(); } bjorn@frodo2:~/src/c++/test$ cat b.cpp #include "b.hpp" //#include "a.hpp" #include "a.cpp" #include <iostream> namespace mylib { int lib_func() { boost::A a; std::cout << a.foo() << std::endl; return 0; } } bjorn@frodo2:~/src/c++/test$ cat c.cpp #include "b.hpp" int main() { return mylib::lib_func(); } bjorn@frodo2:~/src/c++/test$ c++ -c b.cpp bjorn@frodo2:~/src/c++/test$ ar r libmy.a b.o bjorn@frodo2:~/src/c++/test$ c++ c.cpp libmy.a bjorn@frodo2:~/src/c++/test$ ./a.out aaaappp bjorn@frodo2:~/src/c++/test$ nm -C libmy.a b.o: 000000000000007e t global constructors keyed to _ZN5boost1A3fooEv 0000000000000041 t __static_initialization_and_destruction_0(int, int) 0000000000000000 T boost::A::foo() 000000000000000f T mylib::lib_func() U std::ostream::operator<<(std::ostream& (*)(std::ostream&)) U std::ios_base::Init::Init() U std::ios_base::Init::~Init() U std::cout U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) 0000000000000000 b std::__ioinit U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) U __cxa_atexit U __dso_handle U __gxx_personality_v0 bjorn@frodo2:~/src/c++/test$ strip -w -N *boost* libmy.a strip: not stripping symbol `_ZN5boost1A3fooEv' because it is named in a relocation or streaming mangled output through c++filt bjorn@frodo2:~/src/c++/test$ strip -w -N *boost* libmy.a 2>&1 | c++filt strip: not stripping symbol `boost::A::foo()' because it is named in a relocation -- Bjørn ,

On Saturday 27 June 2009, Ilya Bobir wrote:
Unless your "user-defined library" include headers you can not introduce names into a translation unit.
I think you left out a word or something, that sentence wasn't quite coherent.
And even if it does include headers the ODR applies only to the stuff you have in that headers and not to the "rest" of the library.
Not sure what that sentence means either.
It means that unless you have the Boost headers somewhere in the header part of your library there is no way to violate the ODR as it applies to the translation units only.
Nonsense. Two translation units can conflict with each other and violate the one definition rule without having to contain any common header files. And just because one translation unit came from a library instead of "your" code doesn't make it any less a part of the final program, or make the one definition rule apply any less to it. There's nothing in the one definition rule about exceptions to the rules for "translation units that are separated by a library boundary from which internal symbols have been stripped, etc, etc...". The relevant part to multiple definitions residing in separate translation units is paragraph 5 of section 3.2 (as I've mentioned twice before but I'll quote it this time): "There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template special- ization for which some template parameters are not specified (14.7, 14.5.4) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following require- ments. Given such an entity named D defined in more than one translation unit, then — each definition of D shall consist of the same sequence of tokens; and — in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a const object with internal or no linkage if the object has the same integral or enumeration type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D; and — in each definition of D, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same function, or to a function defined within the definition of D; and — in each definition of D, a default argument used by an (implicit or explicit) function call is treated as if its token sequence were present in the definition of D; that is, the default argument is subject to the three requirements described above (and, if the default argument has sub-expressions with default arguments, this requirement applies recursively).25) — if D is a class with an implicitly-declared constructor (12.1), it is as if the constructor was implicitly defined in every translation unit where it is used, and the implicit definition in every translation unit shall call the same constructor for a base class or a class member of D. [Example: // translation unit 1: struct X { X(int); X(int, int); }; X::X(int = 0) { } class D: public X { }; D d2; // X(int) called by D() // translation unit 2: struct X { X(int); X(int, int); }; X::X(int = 0, int = 0) { } class D: public X { }; // X(int, int) called by D(); // D()’s implicit definition // violates the ODR —end example] If D is a template, and is defined in more than one translation unit, then the last four requirements from the list above shall apply to names from the template’s enclosing scope used in the template definition (14.6.3), and also to dependent names at the point of instantiation (14.6.2). If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined."

At 12:49 AM +0000 6/24/09, Lewis Hyatt wrote:
Let's say I want to compile and distribute a library (without the source), and I happen to use some boost header-only libraries as an implementation detail in some of my functions. None of the headers associated with my library include boost headers; it's purely an internal detail.
Now, it seems to me that users of my library will still have to be aware of the fact that I used boost in my implementation -- specifically, if they happen to use different versions of the same boost libraries in their code, then the ODR is violated and the behavior is undefined.
I recently dealt with a similar situation by using a linker version script that marked all of the boost related symbols in the library as local. See the binutils documentation for ld's --version-script option. Of course, this is gnu tool-chain specific, which may or may not be useful to you.
participants (8)
-
Bjørn Roald
-
Christian Schladetsch
-
Edward Diener
-
Frank Mori Hess
-
Frank Mori Hess
-
Ilya Bobir
-
Kim Barrett
-
Lewis Hyatt