Boost inspection notification (2007-06-09/RC_1_34_0) *X*

Boost Inspection Report Run Date: 16:07:01 UTC, Saturday 09 June 2007 An inspection program <http://www.boost.org/tools/inspect/index.html> checks each file in the current Boost CVS for various problems, generating this as output. Problems detected include tabs in files, missing copyrights, broken URL's, and similar misdemeanors. Totals: 11452 files scanned 909 directories scanned (including root) 163 problems reported Problem counts: 0 files with invalid line endings 0 bookmarks with invalid characters 3 invalid urls 71 broken links 21 unlinked files 22 file/directory names issues 2 files with tabs 9 violations of the Boost min/max guidelines 35 usages of unnamed namespaces in headers (including .ipp files) Summary: archive (3) bind (1) boost-root (1) build (1) date_time (1) doc (2) filesystem (3) graph (3) iostreams (2) lambda (3) math (8) more (4) mpl (4) multi_array (2) ptr_container (1) python (8) regex (1) regression (32) serialization (1) test (81) type_traits (1) Details: *R* invalid (cr only) line-ending *A* invalid bookmarks, invalid urls, broken links, unlinked files *N* file/directory names issues *T* tabs in file *M* uses of min or max that have not been protected from the min/max macros, or unallowed #undef-s *U* unnamed namespace in header |archive| boost/archive/basic_streambuf_locale_saver.hpp: *N* name exceeds 31 characters boost/archive/impl/xml_wiarchive_impl.ipp: *U* unnamed namespace at line 53 boost/archive/iterators/remove_whitespace.hpp: *U* unnamed namespace at line 57 |bind| boost/bind/placeholders.hpp: *U* unnamed namespace at line 25 |boost-root| index.htm: *A* broken link: doc/hmtl/date_time/details.html#changes |build| tools/build/v2/test/test_system.html: *A* unlinked file |date_time| libs/date_time/xmldoc/date_time_docs_howto.html: *A* unlinked file |doc| doc/html/boost_math/inverse_complex.html: *A* unlinked file doc/html/jam.html: *A* unlinked file |filesystem| libs/filesystem/doc/do-list.htm: *A* invalid URL (hardwired file): file://?/ *A* invalid URL (hardwired file): file://?/UNC/ libs/filesystem/doc/tr2_proposal.html: *A* invalid URL (hardwired file): file:///C|/boost/site/libs/filesystem/doc/operations.htm#complete_note |graph| boost/graph/relax.hpp: *T* libs/graph/example/file_dependencies.cpp: *M* violation of Boost min/max guidelines on line 139 libs/graph/test/serialize.cpp: *T* |iostreams| libs/iostreams/doc/concepts/multi-character.html: *A* unlinked file libs/iostreams/doc/installation.html: *A* broken link: ../../../tools/build/v1/build_system.htm |lambda| boost/lambda/core.hpp: *U* unnamed namespace at line 62 boost/lambda/detail/lambda_functors.hpp: *U* unnamed namespace at line 25 boost/lambda/exceptions.hpp: *U* unnamed namespace at line 24 |math| libs/math/test/common_factor_test.cpp: *M* violation of Boost min/max guidelines on line 146 *M* violation of Boost min/max guidelines on line 147 *M* violation of Boost min/max guidelines on line 193 *M* violation of Boost min/max guidelines on line 194 |more| more/cvs.html: *A* unlinked file more/getting_started/unix-variants.html: *A* broken link: ../../doc/html/thread/build.html#thread.build more/getting_started/windows.html: *A* broken link: ../../doc/html/thread/build.html#thread.build more/separate_compilation.html: *A* broken link: ../libs/config/test/link/test/Jamfile.v2 |mpl| boost/mpl/alias.hpp: *U* unnamed namespace at line 17 libs/mpl/doc/refmanual/for-each.html: *A* broken link: ./value-initialized.html |multi_array| boost/multi_array/base.hpp: *U* unnamed namespace at line 69 libs/multi_array/test/generative_tests.hpp: *U* unnamed namespace at line 57 |ptr_container| libs/ptr_container/doc/tutorial_example.html: *A* unlinked file |python| libs/python/doc/building.html: *A* broken link: ../index.htm libs/python/doc/tutorial/doc/html/python/hello.html: *A* broken link: ../../../../../example/tutorial/Jamrules libs/python/doc/tutorial/index.html: *A* broken link: ../../../LICENSE_1_0.txt libs/python/doc/v2/May2002.html: *A* broken link: ../../../../tools/build/v1/build_system.htm *A* broken link: ../../../../tools/build/v1/gen_aix_import_file.py libs/python/doc/v2/faq.html: *A* broken link: ../../../../tools/build/v1/build_system.htm |regex| libs/regex/performance/input.html: *A* unlinked file |regression| regression/.htaccess: *N* leading character of ".htaccess" is not alphabetic tools/regression/test/test-cases/incremental/bjam.log.1: *N* name contains more than one dot character ('.') tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/compile-fail.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/completed.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/compile-fail.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/completed.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/lib.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/misfire.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/no-run.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/run_pyd.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/expected/test-case.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/test-case.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_is_test_log_complete/test-driver.xsl: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_re_match/expected/test_re_match.xml: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ tools/regression/xsl_reports/test/test-components/test_test_case_status/explicit-failures-markup.xml.test: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ *N* name contains more than one dot character ('.') *N* name exceeds 31 characters tools/regression/xsl_reports/test/test-components/test_test_structure/explicit-failures-markup.xml.test: *N* file path will exceed 100 characters in a directory tree with a root of the form boost_X_XX_X/ *N* name contains more than one dot character ('.') *N* name exceeds 31 characters tools/regression/xsl_reports/xsl/html/issues_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/html/library_developer_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/html/library_user_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/html/make_tinyurl.html: *A* unlinked file tools/regression/xsl_reports/xsl/html/summary_developer_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/html/summary_user_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/v2/html/issues_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/v2/html/library_developer_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/v2/html/library_user_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/v2/html/make_tinyurl.html: *A* unlinked file tools/regression/xsl_reports/xsl/v2/html/summary_developer_legend.html: *A* unlinked file tools/regression/xsl_reports/xsl/v2/html/summary_user_legend.html: *A* unlinked file |serialization| libs/serialization/src/basic_xml_grammar.ipp: *U* unnamed namespace at line 43 |test| boost/test/floating_point_comparison.hpp: *U* unnamed namespace at line 206 *U* unnamed namespace at line 228 boost/test/impl/cpp_main.ipp: *U* unnamed namespace at line 42 boost/test/impl/exception_safety.ipp: *U* unnamed namespace at line 400 boost/test/impl/framework.ipp: *U* unnamed namespace at line 199 boost/test/impl/plain_report_formatter.ipp: *U* unnamed namespace at line 45 boost/test/impl/progress_monitor.ipp: *U* unnamed namespace at line 38 boost/test/impl/results_collector.ipp: *U* unnamed namespace at line 106 boost/test/impl/results_reporter.ipp: *U* unnamed namespace at line 48 boost/test/impl/unit_test_log.ipp: *U* unnamed namespace at line 79 boost/test/impl/unit_test_monitor.ipp: *U* unnamed namespace at line 35 boost/test/impl/unit_test_parameters.ipp: *U* unnamed namespace at line 50 boost/test/results_collector.hpp: *U* unnamed namespace at line 40 boost/test/test_tools.hpp: *U* unnamed namespace at line 262 boost/test/utils/iterator/token_iterator.hpp: *U* unnamed namespace at line 166 boost/test/utils/named_params.hpp: *U* unnamed namespace at line 216 boost/test/utils/runtime/cla/dual_name_parameter.ipp: *U* unnamed namespace at line 43 boost/test/utils/runtime/cla/modifier.hpp: *U* unnamed namespace at line 34 boost/test/utils/runtime/env/modifier.hpp: *U* unnamed namespace at line 34 boost/test/utils/runtime/file/config_file.hpp: *U* unnamed namespace at line 169 *U* unnamed namespace at line 64 *U* unnamed namespace at line 74 boost/test/utils/runtime/file/config_file_iterator.hpp: *U* unnamed namespace at line 68 boost/test/utils/trivial_singleton.hpp: *U* unnamed namespace at line 52 *U* unnamed namespace at line 61 libs/test/build/msvc71_proj/config_file_iterator_test.vcproj: *N* name exceeds 31 characters libs/test/doc/components/prg_exec_monitor/compilation.html: *A* broken link: ../../../build/Jamfile libs/test/doc/components/prg_exec_monitor/index.html: *A* broken link: ../../../../../boost/test/cpp_main.hpp libs/test/doc/components/test_tools/index.html: *A* broken link: ../../tests/boost_check_equal_str.html libs/test/doc/components/test_tools/reference/BOOST_CHECK_CLOSE.html: *A* broken link: BOOST_CHECK_CLOSE_FRACTION.html libs/test/doc/components/test_tools/reference/BOOST_CHECK_MESSAGE.html: *A* broken link: BOOST_MESSAGE.html libs/test/doc/components/test_tools/reference/BOOST_CHECK_SMALL.html: *A* broken link: BOOST_CHECK_CLOSE_FRACTION.html libs/test/doc/components/test_tools/reference/tools_list.html: *A* broken link: ../../btl1.gif *A* broken link: BOOST_CHECK_CLOSE_FRACTION.html libs/test/doc/components/utf/compilation.html: *A* broken link: ../../../build/Jamfile libs/test/doc/components/utf/components/index.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/components/test_case/abstract_interface.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/auto_register_facility.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/boost_function_tc.html: *A* broken link: ../../../../../../../boost/test/unit_test_suite_ex.hpp *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/class_tc.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/function_tc.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/index.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/param_boost_function_tc.html: *A* broken link: ../../../../../../../boost/test/unit_test_suite_ex.hpp *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/param_class_tc.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/param_function_tc.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_case/tc_template.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_log/custom_log_formatter.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_log/index.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_result/index.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/components/test_suite/index.html: *A* broken link: ../../../btl1.gif libs/test/doc/components/utf/index.html: *A* broken link: getting_started/index.html libs/test/doc/components/utf/parameters/build_info.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/catch_system_errors.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/detect_memory_leaks.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/index.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/log_format.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/log_level.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/no_result_code.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/output_format.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/random.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/report_format.html: *A* broken link: ../../../../../LICENSE_1_0.txt *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/report_level.html: *A* broken link: ../../btl1.gif libs/test/doc/components/utf/parameters/show_progress.html: *A* broken link: ../../btl1.gif libs/test/doc/examples/unit_test_example1.html: *A* broken link: ../../example/unit_test_example1.cpp libs/test/doc/examples/unit_test_example2.html: *A* broken link: ../../example/unit_test_example2.cpp libs/test/doc/examples/unit_test_example3.html: *A* broken link: ../../example/unit_test_example3.cpp libs/test/doc/examples/unit_test_example4.html: *A* broken link: ../../example/unit_test_example4.cpp libs/test/doc/examples/unit_test_example5.html: *A* broken link: ../../example/unit_test_example5.cpp *A* broken link: ../../example/unit_test_example5.input libs/test/doc/tests/auto_unit_test_test.html: *A* broken link: ../../test/auto_unit_test_test.cpp libs/test/doc/tests/auto_unit_test_test_mult.html: *A* broken link: ../../test/auto_unit_test_test_mult1.cpp *A* broken link: ../../test/auto_unit_test_test_mult2.cpp libs/test/doc/tests/unit_test_suite_ex_test.html: *A* broken link: ../../test/unit_test_suite_ex_test.cpp libs/test/doc/tutorials/hello_the_testing_world.html: *A* broken link: ../../../../../LICENSE_1_0.txt *A* broken link: ../execution_monitor/index.html libs/test/doc/tutorials/new_year_resolution.html: *A* broken link: ../../../../../../LICENSE_1_0.txt |type_traits| libs/type_traits/cxx_type_traits.htm: *A* unlinked file

|test| boost/test/floating_point_comparison.hpp: *U* unnamed namespace at line 206 *U* unnamed namespace at line 228 boost/test/impl/cpp_main.ipp: *U* unnamed namespace at line 42 boost/test/impl/exception_safety.ipp: *U* unnamed namespace at line 400 boost/test/impl/framework.ipp: *U* unnamed namespace at line 199 boost/test/impl/plain_report_formatter.ipp: *U* unnamed namespace at line 45 boost/test/impl/progress_monitor.ipp: *U* unnamed namespace at line 38 boost/test/impl/results_collector.ipp: *U* unnamed namespace at line 106 boost/test/impl/results_reporter.ipp: *U* unnamed namespace at line 48 boost/test/impl/unit_test_log.ipp: *U* unnamed namespace at line 79 boost/test/impl/unit_test_monitor.ipp: *U* unnamed namespace at line 35 boost/test/impl/unit_test_parameters.ipp: *U* unnamed namespace at line 50 boost/test/results_collector.hpp: *U* unnamed namespace at line 40 boost/test/test_tools.hpp: *U* unnamed namespace at line 262 boost/test/utils/iterator/token_iterator.hpp: *U* unnamed namespace at line 166 boost/test/utils/named_params.hpp: *U* unnamed namespace at line 216 boost/test/utils/runtime/cla/dual_name_parameter.ipp: *U* unnamed namespace at line 43 boost/test/utils/runtime/cla/modifier.hpp: *U* unnamed namespace at line 34 boost/test/utils/runtime/env/modifier.hpp: *U* unnamed namespace at line 34 boost/test/utils/runtime/file/config_file.hpp: *U* unnamed namespace at line 169 *U* unnamed namespace at line 64 *U* unnamed namespace at line 74 boost/test/utils/runtime/file/config_file_iterator.hpp: *U* unnamed namespace at line 68 boost/test/utils/trivial_singleton.hpp: *U* unnamed namespace at line 52 *U* unnamed namespace at line 61
Can anyone explain why unnamed namespace is a problem?? Gennadiy

Le samedi 09 juin 2007 à 14:03 -0400, Gennadiy Rozental a écrit :
Can anyone explain why unnamed namespace is a problem?
Inline functions referring to the content of an unnamed namespace will break the one-definition rule, when their header is included several times. Undefined behavior ensues. The following example should make it clear: // h.hpp namespace { int a; } inline int f() { return ++a; } // a.cpp #include "h.hpp" void g() { f(); } // b.cpp #include "h.hpp" void g(); int main() { g(); return f(); } Which value does this program return? Depending on the compiler and on the level of optimization, it could be either 1 or 2. If you use a named namespace instead, the behavior becomes deterministic and the returned value is necessarily 2. Best regards, Guillaume

"Guillaume Melquiond" <guillaume.melquiond@ens-lyon.fr> wrote in message news:1181413681.3738.16.camel@liege.msr-inria.inria.fr...
Le samedi 09 juin 2007 à 14:03 -0400, Gennadiy Rozental a écrit :
Can anyone explain why unnamed namespace is a problem?
Inline functions referring to the content of an unnamed namespace will break the one-definition rule, when their header is included several times. Undefined behavior ensues.
I don't mean in general. static vars have the same issue. I mean why is it reported by our tools? Gennadiy

Gennadiy Rozental wrote:
I don't mean in general. static vars have the same issue. I mean why is it reported by our tools?
Because, once upon a time, we found real ODR problems in some of the headers that use(d) unnamed namespaces. And someone decided that it would be a good idea find as many of those as possible. And what better way to do that, than an automated tool. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo

"Rene Rivera" <grafikrobot@gmail.com> wrote in message news:466B304C.6060400@gmail.com...
Gennadiy Rozental wrote:
I don't mean in general. static vars have the same issue. I mean why is it reported by our tools?
Because, once upon a time, we found real ODR problems in some of the headers that use(d) unnamed namespaces. And someone decided that it would be a good idea find as many of those as possible. And what better way to do that, than an automated tool.
I don't believe it right approach. Almost every feature can be misused.Should we report usage of any one of them? It there any problems with unnamed namespace usage within Boost.Test? Gennadiy

Gennadiy Rozental wrote:
Almost every feature can be misused.Should we report usage of any one of them?
Yes, if something exists, it can be misused :-) If we can detect problems that can be serious, yes we should attempt to report them. Do you know of others?
It there any problems with unnamed namespace usage within Boost.Test?
I have no clue. The point is to try and push /you/ into looking at them ;-) PS. Why do I get a feeling of deja vu. I seem to remember sending an almost exact version of this post long ago. Weird. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com -- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo

"Rene Rivera" <grafikrobot@gmail.com> wrote in message news:466B3A16.9050308@gmail.com...
Gennadiy Rozental wrote:
It there any problems with unnamed namespace usage within Boost.Test?
I have no clue. The point is to try and push /you/ into looking at them ;-)
The only thing this "point" achieves is me now ignoring any reports. You can't report "N problems detected" if you just suspect something might be misused. Gennadiy

"Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote
It there any problems with unnamed namespace usage within Boost.Test?
Using unnamed namespace inside a header represents a potential ODR violation. See if you have this kind of usage. Regards, Arkadiy

To say this another way, there is never an unnamed namespace; any namespace for which you do not specify a name is effectively given a randomly generated name. That means each time you include a header file with an "unnamed" namespace, you are creating a separate instance of everything in that namespace. On 6/10/07, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote
Are there any problems with unnamed namespace usage within Boost.Test?
Using unnamed namespace inside a header represents a potential ODR violation. See if you have this kind of usage.
Regards, Arkadiy

"Bryan Ewbank" <ewbank@gmail.com> wrote
To say this another way, there is never an unnamed namespace; any namespace for which you do not specify a name is effectively given a randomly generated name. That means each time you include a header file with an "unnamed" namespace, you are creating a separate instance of everything in that namespace.
Which by itself is not a problem, unless it is used in the definition of yet another class, defined in a header and _not_ inside unnamed namespace. This another class, when #included from different TUs, becomes defined differently in different TUs, hence ODR violation. Regards, Arkadiy
On 6/10/07, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote
Are there any problems with unnamed namespace usage within Boost.Test?
Using unnamed namespace inside a header represents a potential ODR violation. See if you have this kind of usage.
Regards, Arkadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Le samedi 09 juin 2007 à 18:43 -0400, Gennadiy Rozental a écrit :
Can anyone explain why unnamed namespace is a problem?
Inline functions referring to the content of an unnamed namespace will break the one-definition rule, when their header is included several times. Undefined behavior ensues.
I don't mean in general. static vars have the same issue. I mean why is it reported by our tools?
I don't mean in general either. The example I give you is based on your very own files. They contain unnamed namespaces used from inline functions, hence they are not compliant with the C++ standard. For example, see the token_iterator.hpp file detected by the inspection reports. The keep_empty_tokens variable is defined in an unnamed namespace but used in an inline function, so the one that is passed as an argument to the function may not be identical to the one the function tests for. Not that it may change anything, but this is not standard C++, which is a bit unfortunate for a Boost library. Moreover, it artificially increases the linking time and the size of the execution files for no good reason. Best regards, Guillaume

Guillaume Melquiond wrote:
Le samedi 09 juin 2007 à 18:43 -0400, Gennadiy Rozental a écrit :
Can anyone explain why unnamed namespace is a problem?
Inline functions referring to the content of an unnamed namespace will break the one-definition rule, when their header is included several times. Undefined behavior ensues.
I don't mean in general. static vars have the same issue. I mean why is it reported by our tools?
I don't mean in general either. The example I give you is based on your very own files. They contain unnamed namespaces used from inline functions, hence they are not compliant with the C++ standard.
For example, see the token_iterator.hpp file detected by the inspection reports. The keep_empty_tokens variable is defined in an unnamed namespace but used in an inline function, so the one that is passed as an argument to the function may not be identical to the one the function tests for.
Not that it may change anything, but this is not standard C++, which is a bit unfortunate for a Boost library. Moreover, it artificially increases the linking time and the size of the execution files for no good reason.
Best regards,
Guillaume
Looking at the inspection notifications it seems unnamed namespaces are in fact one of if not in fact the largest real (Broken links aside) offender. I have used them sometimes but only in source files not in headers(Unless you can GUARANTEE it will only be included once. Doubtful). I only use them when they are intended to be private to the file in question. When I don't want someone to just be able to extern it and reference from another file for example. But there has to be a compelling reason to do so. I only use them for constants or classes, no statics as thats what the unnamed namespace is for in the first place IMO. No globals either. Globals are another discussion entirely but I digress. Basically if boost is striving for header only libraries when ever possible(And that is my impression) should there be unnamed namespace's being used at all ? Best Regards, Richard Day

"Richard Day" <richardvday@verizon.net> wrote
Basically if boost is striving for header only libraries when ever possible(And that is my impression)
I don't think this is 100% correct. In my impression Boost is a combinatiom of libraries produced by different people (or different groups of people). Each library author has his/her only preference regarding splitting the code between headers and source files.
should there be unnamed namespace's being used at all ?
The main problem of unnamed namespaces in headers is the possibility of ODR violation. Has anyone seen any compiler complain about this? In Typeof library we specifically implement test cases to cause ODR violation (because we do use unnamed namespaces in headers; only since they are hidden inside macro definitions, we don't get inspection complains). No compiler complains of any ODR so far. Now, I don't know if this is an appropriate topic here, but I would question the usefullness of the ODR itself. My main problem with it -- it contradicts to quite useful, IMO, idiom, where a library author defines a main template in his/her library as a customization point, and the users provide specializations of this template (similar to virtual functions in runtime world). Regards, Arkadiy

The main problem of unnamed namespaces in headers is the possibility of ODR violation. Has anyone seen any compiler complain about this? Not this case specifically, although I've seen complaints about more obvious violations of the ODR, e.g. when you try to link against two versions of the CRT in Visual C++. (Typically because you specify one and a static library you include has another in its dependencies.) Now, I don't know if this is an appropriate topic here, but I would question the usefullness of the ODR itself. The ODR is a logical necessity, not a feature that may be useful or not. If the compiler generates two differing definitions of a symbol, how can
Arkadiy Vertleyb wrote: the linker possibly know which one to use? And if it doesn't know which one to use, how can the program have defined behaviour? A better question would be whether to relax the ODR such that "equivalent" (under specific rules) multiple definitions do not cause the ODR to be violated, similar to what is already done for template instantiations.
My main problem with it -- it contradicts to quite useful, IMO, idiom, where a library author defines a main template in his/her library as a customization point, and the users provide specializations of this template (similar to virtual functions in runtime world).
What does this have to do with the ODR? Sebastian Redl

"Sebastian Redl" <sebastian.redl@getdesigned.at> wrote
Now, I don't know if this is an appropriate topic here, but I would question the usefullness of the ODR itself. The ODR is a logical necessity, not a feature that may be useful or not. If the compiler generates two differing definitions of a symbol, how can
Arkadiy Vertleyb wrote: the linker possibly know which one to use? And if it doesn't know which one to use, how can the program have defined behaviour? A better question would be whether to relax the ODR such that "equivalent" (under specific rules) multiple definitions do not cause the ODR to be violated, similar to what is already done for template instantiations.
OK
My main problem with it -- it contradicts to quite useful, IMO, idiom, where a library author defines a main template in his/her library as a customization point, and the users provide specializations of this template (similar to virtual functions in runtime world).
What does this have to do with the ODR?
One example: The library author defines a main template; The users A and B provide specializations for their classes; One TU includes the library header, and the header A; Another TU includes the library header, the header A, and B. Now the template is defined differently in different TUs. Another example (from the Typeof library): Types and templates are mapped to unique numbers using preprocessor counter. The resulting specializations depend on the order these specializations are seen by the preprocessor, and therefore on the order of inclusion. Regards, Arkadiy

Arkadiy Vertleyb wrote:
One example:
The library author defines a main template; The users A and B provide specializations for their classes; One TU includes the library header, and the header A; Another TU includes the library header, the header A, and B.
Now the template is defined differently in different TUs.
That's fine, so long as the template is not instantiated differently in different translation units. The ODR is about the actual use of inconsistent definitions. If someone instantiations the primary template with a class from A in one TU, and then in another TU instantiations the same template with the same class from A, but this time picks up a specialization, then we have an ODR violation. Merely the presence of an unused specialization does not cause an ODR violation.
Another example (from the Typeof library):
Types and templates are mapped to unique numbers using preprocessor counter. The resulting specializations depend on the order these specializations are seen by the preprocessor, and therefore on the order of inclusion.
The Typeof library is a great thing, but the techniques needed to simulate what should be a language feature are C++ hacks. We don't need to loosen or fix the ODR, we need the functionality that the Typeof library provides ("give me the type of this expression!") to be in the language. decltype fixes that. - Doug

"Douglas Gregor" <dgregor@osl.iu.edu> wrote in message
Arkadiy Vertleyb wrote:
Another example (from the Typeof library):
Types and templates are mapped to unique numbers using preprocessor counter. The resulting specializations depend on the order these specializations are seen by the preprocessor, and therefore on the order of inclusion.
The Typeof library is a great thing, but the techniques needed to simulate what should be a language feature are C++ hacks. We don't need to loosen or fix the ODR, we need the functionality that the Typeof library provides ("give me the type of this expression!") to be in the language. decltype fixes that.
I did not suggest that C++ standard should be fixed to make the Typeof library 100% compliant ;-) My point was to mention the technique used; this technique (generating template specializations on demand, and maybe using preprocessor counter to give them unique numbers) might be useful in other contexts... Or it might be not. Regards, Arkadiy

Arkadiy Vertleyb wrote:
I did not suggest that C++ standard should be fixed to make the Typeof library 100% compliant ;-)
My point was to mention the technique used; this technique (generating template specializations on demand, and maybe using preprocessor counter to give them unique numbers) might be useful in other contexts...
Or it might be not.
I've used this technique a handful of times before, and each time I've decided that what I did was an awful hack, never to be repeated. Your mileage may vary :) - Doug

"Douglas Gregor" <dgregor@osl.iu.edu> wrote
Arkadiy Vertleyb wrote:
I did not suggest that C++ standard should be fixed to make the Typeof library 100% compliant ;-)
My point was to mention the technique used; this technique (generating template specializations on demand, and maybe using preprocessor counter to give them unique numbers) might be useful in other contexts...
Or it might be not.
I've used this technique a handful of times before, and each time I've decided that what I did was an awful hack, never to be repeated. Your mileage may vary :)
So you applied it the first time, decided that it was "never to be repeated", and stll used it a few more times ;-) Or am I missing your point? Regards, Arkadiy

"Douglas Gregor" <dgregor@osl.iu.edu> wrote
Arkadiy Vertleyb wrote:
One example:
The library author defines a main template; The users A and B provide specializations for their classes; One TU includes the library header, and the header A; Another TU includes the library header, the header A, and B.
Now the template is defined differently in different TUs.
That's fine, so long as the template is not instantiated differently in different translation units. The ODR is about the actual use of inconsistent definitions. If someone instantiations the primary template with a class from A in one TU, and then in another TU instantiations the same template with the same class from A, but this time picks up a specialization, then we have an ODR violation. Merely the presence of an unused specialization does not cause an ODR violation.
And, since the instantiation itself is done by the library user, and the library author can't know how it will be done, this technique must be prohibited according to ODR. Regards, Arkadiy

Arkadiy Vertleyb wrote:
"Douglas Gregor" <dgregor@osl.iu.edu> wrote
That's fine, so long as the template is not instantiated differently in different translation units. And, since the instantiation itself is done by the library user, and the library author can't know how it will be done, this technique must be prohibited according to ODR.
The ODR doesn't prohibit techniques, merely occurrences. If the library specializes the template for its types, then it should do so in a way that the specialization is visible whenever the type is visible. Otherwise, yes, ODR can occur. Or, if the library doesn't want to introduce the unavoidable dependency, it should document very clearly that, in order to use both this library and the library providing the template, the client must include the header that provides the specialization. But this doesn't make the technique invalid. Sebastian Redl

"Sebastian Redl" <sebastian.redl@getdesigned.at> wrote
Arkadiy Vertleyb wrote:
"Douglas Gregor" <dgregor@osl.iu.edu> wrote
That's fine, so long as the template is not instantiated differently in different translation units. And, since the instantiation itself is done by the library user, and the library author can't know how it will be done, this technique must be prohibited according to ODR.
The ODR doesn't prohibit techniques, merely occurrences.
If the library specializes the template for its types, then it should do so in a way that the specialization is visible whenever the type is visible. Otherwise, yes, ODR can occur.
Or, if the library doesn't want to introduce the unavoidable dependency, it should document very clearly that, in order to use both this library and the library providing the template, the client must include the header that provides the specialization.
But this doesn't make the technique invalid.
I would say that, if your technique, as a library author, can easily lead to the violation of language rules by your users, even though these users don't do anything obviously wrong, such technique can be defined as invalid. Regards, Arkadiy

Arkadiy Vertleyb wrote:
I would say that, if your technique, as a library author, can easily lead to the violation of language rules by your users, even though these users don't do anything obviously wrong, such technique can be defined as invalid.
Define "easily", then. If the documentation of the library says, in a sufficiently prominent location: "If you want to use this library together with XYZ, you must include xyz-interop.hpp in all translation units that do so." Does ignoring this count as "easy"? Sebastian Redl

"Sebastian Redl" <sebastian.redl@getdesigned.at> wrote
Arkadiy Vertleyb wrote:
I would say that, if your technique, as a library author, can easily lead to the violation of language rules by your users, even though these users don't do anything obviously wrong, such technique can be defined as invalid.
Define "easily", then.
I have to admit that using a main template for a type in one TU, and a specialization for the same in another TU probably doesn't make a lot of sense, and one can further enforce using specialization by not providing the definition of the main template. So, my example doesn't hold. Regards, Arkadiy

Sebastian Redl wrote:
Arkadiy Vertleyb wrote:
I would say that, if your technique, as a library author, can easily lead to the violation of language rules by your users, even though these users don't do anything obviously wrong, such technique can be defined as invalid.
Define "easily", then.
If the documentation of the library says, in a sufficiently prominent location: "If you want to use this library together with XYZ, you must include xyz-interop.hpp in all translation units that do so." Does ignoring this count as "easy"?
Just want to point out that the problem is larger than just unnamed namespaces. Global const objects are also given internal linkage. // foo.hpp struct placeholder {}; placeholder const _1 = {}; template<class T> void foo(T const &) { // use _1 here } That's a potential ODR violation right there. Every translation unit that includes foo.hpp gets it's own _1 object. Therefore, the foo() template gets instantiated differently in each TU. Dave and I spent a long time, and started a discussion on the std reflectors, figuring out how to avoid ODR in this very common and useful scenario without giving up static initialization. It's hard and not obvious: template<typename T> struct static_const { static T const value; }; template<typename T> T const static_const<T>::value = {}; struct placeholder {}; // This is *supposed* to be statically initialized but many // compilers do dynamic initialization for it. :-( placeholder const &_1 = static_const<placeholder>::value; template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. } -- Eric Niebler Boost Consulting www.boost-consulting.com

on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
// This is *supposed* to be statically initialized but many // compilers do dynamic initialization for it. :-( placeholder const &_1 = static_const<placeholder>::value;
I thought it was just MSVC. Any others? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
// This is *supposed* to be statically initialized but many // compilers do dynamic initialization for it. :-( placeholder const &_1 = static_const<placeholder>::value;
I thought it was just MSVC. Any others?
Shoot, now I can't remember. How many did we test? Well, this much is certain, there is at least one compiler that does dynamic initialization for it. :-/ I also seem to recall that there was still some question as to whether the use of the reference violated the ODR, if the reference is not optimized away. I don't think we ever got an answer to that question. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

----- Mensaje original ----- De: Eric Niebler <eric@boost-consulting.com> Fecha: Jueves, Junio 14, 2007 10:57 pm Asunto: Re: [boost] Unnamed namespaces? Para: boost@lists.boost.org
David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:>
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
// This is *supposed* to be statically initialized but many // compilers do dynamic initialization for it. :-( placeholder const &_1 = static_const<placeholder>::value;
I thought it was just MSVC. Any others?
Shoot, now I can't remember. How many did we test? Well, this much is certain, there is at least one compiler that does dynamic initialization for it. :-/
I also seem to recall that there was still some question as to whether the use of the reference violated the ODR, if the reference is not optimized away. I don't think we ever got an answer to that question.
Maybe the following is not relevant to the discussion, but I recall a post by Anthony Williams which shows how to create a _1-like global entity in an entirely ODR-abiding way: http://lists.boost.org/Archives/boost/2006/07/108355.php HTH, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN LOPEZ MU?Z wrote:
Maybe the following is not relevant to the discussion, but I recall a post by Anthony Williams which shows how to create a _1-like global entity in an entirely ODR-abiding way:
This is not a general technique. For applications like Lambda, things like _1[i] should be possible, and that's not possible if _1 is a pointer to an inline function. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Eric Niebler wrote:
JOAQUIN LOPEZ MU?Z wrote:
Maybe the following is not relevant to the discussion, but I recall a post by Anthony Williams which shows how to create a _1-like global entity in an entirely ODR-abiding way:
This is not a general technique. For applications like Lambda, things like _1[i] should be possible, and that's not possible if _1 is a pointer to an inline function.
Yep. _1 == _2, _1 == 0 are even worse because they compile. There is also template<class T> void f( T const & t ) { T t2( t ); } int main() { f( _1 ); }

on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
// This is *supposed* to be statically initialized but many // compilers do dynamic initialization for it. :-( placeholder const &_1 = static_const<placeholder>::value;
I thought it was just MSVC. Any others?
Shoot, now I can't remember. How many did we test? Well, this much is certain, there is at least one compiler that does dynamic initialization for it. :-/
I also seem to recall that there was still some question as to whether the use of the reference violated the ODR, if the reference is not optimized away. I don't think we ever got an answer to that question.
I don't think there ever was any question about that. At least, I never had a question about it. References don't have any identity distinct from the object they reference. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
I also seem to recall that there was still some question as to whether the use of the reference violated the ODR, if the reference is not optimized away. I don't think we ever got an answer to that question.
I don't think there ever was any question about that. At least, I never had a question about it. References don't have any identity distinct from the object they reference.
Funny you should say that, since you were the one who sent the "Are references subject to ODR?" question to the std reflector:
David Abrahams <dave@boost-consulting.com> 4/1/06 reply-to c++std-core@accu.org to undisclosed-recipients <> date Apr 1, 2006 9:02 AM subject Are references subject to ODR? To: C++ core language mailing list Message c++std-core-11390
Is the following program legal?
// a.cpp int x; int& y = x;
// b.cpp extern int x; int& y = x;
My impression is that it is not legal because references are not explicitly given an exemption in 3.2/5
If I am right, should it be so? It's hard to imagine how this could be a problem.
The result of ensuing discussion was that a reference is a pointer, and so they *do* have identity. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
I also seem to recall that there was still some question as to whether the use of the reference violated the ODR, if the reference is not optimized away. I don't think we ever got an answer to that question.
I don't think there ever was any question about that. At least, I never had a question about it. References don't have any identity distinct from the object they reference.
Funny you should say that, since you were the one who sent the "Are references subject to ODR?" question to the std reflector:
David Abrahams <dave@boost-consulting.com> 4/1/06 reply-to c++std-core@accu.org to undisclosed-recipients <> date Apr 1, 2006 9:02 AM subject Are references subject to ODR? To: C++ core language mailing list Message c++std-core-11390
Is the following program legal?
// a.cpp int x; int& y = x;
// b.cpp extern int x; int& y = x;
My impression is that it is not legal because references are not explicitly given an exemption in 3.2/5
If I am right, should it be so? It's hard to imagine how this could be a problem.
The result of ensuing discussion was that a reference is a pointer, and so they *do* have identity.
That's a different question than I thought you were referring to. I would put the reference itself in an unnamed namespace, and I'm pretty sure that handles it. As long as the reference refers to something not in an unnamed namespace: template<typename T> struct static_const { static T const value; }; template<typename T> T const static_const<T>::value = {}; struct placeholder {}; namespace // <<============== HERE { placeholder const &_1 = static_const<placeholder>::value; } template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. It doesn't matter that the // reference is has a different identity; the object is // the same: static_const<placeholder>::value } -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
The result of ensuing discussion was that a reference is a pointer, and so they *do* have identity.
That's a different question than I thought you were referring to. I would put the reference itself in an unnamed namespace, and I'm pretty sure that handles it. As long as the reference refers to something not in an unnamed namespace:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace // <<============== HERE { placeholder const &_1 = static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. It doesn't matter that the // reference is has a different identity; the object is // the same: static_const<placeholder>::value }
Does that really change anything? Imagine replacing the reference with a const pointer, and the potential for an ODR violation becomes more obvious: template<typename T> struct static_const { static T const value; }; template<typename T> T const static_const<T>::value = {}; struct placeholder {}; namespace { placeholder const *const _1 = &static_const<placeholder>::value; } template<class T> void foo(T const &) { // use *_1 here. Even though *_1 refers to the same // object, we're indirecting through a different pointer // in different TUs. ODR violation? } Since you're indirecting through a different pointer, the code generated for foo() would be different in different translation units. Isn't that a violation of the ODR? -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
David Abrahams wrote:
I would put the reference itself in an unnamed namespace, and I'm pretty sure that handles it. As long as the reference refers to something not in an unnamed namespace:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace // <<============== HERE { placeholder const &_1 = static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. It doesn't matter that the // reference is has a different identity; the object is // the same: static_const<placeholder>::value }
Does that really change anything? Imagine replacing the reference with a const pointer, and the potential for an ODR violation becomes more obvious:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace { placeholder const *const _1 = &static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use *_1 here. Even though *_1 refers to the same // object, we're indirecting through a different pointer // in different TUs. ODR violation? }
Since you're indirecting through a different pointer, the code generated for foo() would be different in different translation units. Isn't that a violation of the ODR?
The difference is that the references themselves do not have an address. The address is the only feature of those two const pointers that makes them observably distinct. The core gods, of course, may still disagree :-) -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
Does that really change anything? Imagine replacing the reference with a const pointer, and the potential for an ODR violation becomes more obvious:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace { placeholder const *const _1 = &static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use *_1 here. Even though *_1 refers to the same // object, we're indirecting through a different pointer // in different TUs. ODR violation? }
Since you're indirecting through a different pointer, the code generated for foo() would be different in different translation units. Isn't that a violation of the ODR?
The difference is that the references themselves do not have an address.
Well, I don't think this is strictly true. You can't /take/ its address, but that doesn't mean that a reference doesn't have one. It may very well occupy space, and therefore have an address. As Mike Miller said in response to your question:
The conceptual model of references is that they behave just like objects with respect to linkage and order of initialization. This allows (but does not require) them to be implemented as const pointers with implicit indirection.
So as far as the standard is concerned (and as far as I understand it), "reference == const pointer" is a good approximation.
The address is the only feature of those two const pointers that makes them observably distinct. The core gods, of course, may still disagree :-)
I dug back into the standard, and I see in 3.2/5, referring to an inline function D with external linkage, which may appear in multiple translation units...
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,
Which made me wonder, if _1 is a reference, what is the "entity" it refers to? If a reference is really a pointer with implicit indirection, I could imagine that the "entity" is actually the pointer rather than the object pointed to, which would be trouble. But no ... in 3/3, I see:
An entity is a value, object, subobject, base class subobject, array element, variable, function, instance of a function, enumerator, type, class member, template, or namespace.
A reference is not an entity. Whew. So I think we're ok. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

on Fri Jun 15 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
David Abrahams wrote:
on Thu Jun 14 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
Does that really change anything? Imagine replacing the reference with a const pointer, and the potential for an ODR violation becomes more obvious:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace { placeholder const *const _1 = &static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use *_1 here. Even though *_1 refers to the same // object, we're indirecting through a different pointer // in different TUs. ODR violation? }
Since you're indirecting through a different pointer, the code generated for foo() would be different in different translation units. Isn't that a violation of the ODR?
The difference is that the references themselves do not have an address.
Well, I don't think this is strictly true. You can't /take/ its address, but that doesn't mean that a reference doesn't have one. It may very well occupy space, and therefore have an address. As Mike Miller said in response to your question:
The conceptual model of references is that they behave just like objects with respect to linkage and order of initialization. This allows (but does not require) them to be implemented as const pointers with implicit indirection.
So as far as the standard is concerned (and as far as I understand it), "reference == const pointer" is a good approximation.
Yes, from a conceptual/implementation POV. However, whether it's a violation of standard rules or not has to rest on standard wording and definitions, and AFAICT there's no support in the standard for the view that a reference is an object.
The address is the only feature of those two const pointers that makes them observably distinct. The core gods, of course, may still disagree :-)
I dug back into the standard, and I see in 3.2/5, referring to an inline function D with external linkage, which may appear in multiple translation units...
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,
Which made me wonder, if _1 is a reference, what is the "entity" it refers to? If a reference is really a pointer with implicit indirection, I could imagine that the "entity" is actually the pointer rather than the object pointed to,
How could you imagine that?
which would be trouble. But no ... in 3/3, I see:
An entity is a value, object, subobject, base class subobject, array element, variable, function, instance of a function, enumerator, type, class member, template, or namespace.
A reference is not an entity. Whew. So I think we're ok.
Yep, I think you are seeing things the same way as I am. IMO if the core gods want to make this an ODR violation they're going to have to change standard language to do so :). -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

On 6/15/07, David Abrahams <dave@boost-consulting.com> wrote:
[...] I would put the reference itself in an unnamed namespace, and I'm pretty sure that handles it. As long as the reference refers to something not in an unnamed namespace:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace // <<============== HERE { placeholder const &_1 = static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. It doesn't matter that the // reference is has a different identity; the object is // the same: static_const<placeholder>::value }
Instead of using a class statics, I've been using function static locals, the same trick used by the BOOST_PARAMETER_KEYWORD macro. What are the advantages and the disadvantages of the two aproach? Consider that I'm using the trick to name stateless function objects in header files These function objects sometime have a constructors, but I could easily make all of them POD if this would force the compiler to use static initialization. Anyways, why is it a necessity to have those objects statically initialized even if they are stateless? gpd

Giovanni Piero Deretta wrote:
On 6/15/07, David Abrahams <dave@boost-consulting.com> wrote:
[...] I would put the reference itself in an unnamed namespace, and I'm pretty sure that handles it. As long as the reference refers to something not in an unnamed namespace:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace // <<============== HERE { placeholder const &_1 = static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. It doesn't matter that the // reference is has a different identity; the object is // the same: static_const<placeholder>::value }
Instead of using a class statics, I've been using function static locals, the same trick used by the BOOST_PARAMETER_KEYWORD macro. What are the advantages and the disadvantages of the two aproach?
Function static locals are not initialized until a thread of execution passes over their declaration. That means no static initialization, IIUC.
Consider that I'm using the trick to name stateless function objects in header files These function objects sometime have a constructors, but I could easily make all of them POD if this would force the compiler to use static initialization.
'Fraid not. And the Boost.Parameter trick looks like this, IIRC: type const &name = get_static_local<type>(); Then this *really* doesn't do static initialization, because you're calling a function.
Anyways, why is it a necessity to have those objects statically initialized even if they are stateless?
If you are using the above formulation, then the reference is not initialized until runtime. Due to order of initialization issues, you could end up indirecting through an uninitialized reference and crash even before you hit main(). I think BOOST_PARAMETER_KEYWORD is bad voodoo and should be changed, FWIW. -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

On 6/15/07, Eric Niebler <eric@boost-consulting.com> wrote:
Giovanni Piero Deretta wrote:
On 6/15/07, David Abrahams <dave@boost-consulting.com> wrote:
[...] I would put the reference itself in an unnamed namespace, and I'm pretty sure that handles it. As long as the reference refers to something not in an unnamed namespace:
template<typename T> struct static_const { static T const value; };
template<typename T> T const static_const<T>::value = {};
struct placeholder {};
namespace // <<============== HERE { placeholder const &_1 = static_const<placeholder>::value; }
template<class T> void foo(T const &) { // use _1 here. OK, _1 refers to the same object // in all translation units. It doesn't matter that the // reference is has a different identity; the object is // the same: static_const<placeholder>::value }
Instead of using a class statics, I've been using function static locals, the same trick used by the BOOST_PARAMETER_KEYWORD macro. What are the advantages and the disadvantages of the two aproach?
Function static locals are not initialized until a thread of execution passes over their declaration. That means no static initialization, IIUC.
IIRC there are some cases where even function static locals are guaranteed to be still initialized statically, but I do not remember exactly in what cases (probably pods initialized with constants), anyways, your observation below makes this useless in my case.
Consider that I'm using the trick to name stateless function objects in header files These function objects sometime have a constructors, but I could easily make all of them POD if this would force the compiler to use static initialization.
'Fraid not. And the Boost.Parameter trick looks like this, IIRC:
type const &name = get_static_local<type>();
That exactly what I'm doing.
Then this *really* doesn't do static initialization, because you're calling a function.
You are definitely right.
Anyways, why is it a necessity to have those objects statically initialized even if they are stateless?
If you are using the above formulation, then the reference is not initialized until runtime. Due to order of initialization issues, you could end up indirecting through an uninitialized reference and crash even before you hit main().
I feared something like that. I'll change my code to use a class template static. Hopfully most of the usages are protected by a macro and I only need to change that.
I think BOOST_PARAMETER_KEYWORD is bad voodoo and should be changed, FWIW.
thanks! gpd

Eric Niebler wrote:
If you are using the above formulation, then the reference is not initialized until runtime. Due to order of initialization issues, you could end up indirecting through an uninitialized reference and crash even before you hit main().
Sorry, could you give me any example such that type const &name = get_static_local<type>(); might cause a crash? Regards, -- Shunsuke Sogame

shunsuke wrote:
Eric Niebler wrote:
If you are using the above formulation, then the reference is not initialized until runtime. Due to order of initialization issues, you could end up indirecting through an uninitialized reference and crash even before you hit main().
Sorry, could you give me any example such that type const &name = get_static_local<type>(); might cause a crash?
////////// //test.hpp template<typename T> T const & get_static_local() { static S const s; return s; } struct S { int i; }; namespace { S const & s = get_static_local<S>(); } S const & get1(); S const & get2(); //////////// // test1.cpp #include "./test.hpp" S const & get1( ) { return s; } int i = get2().i; //////////// // test2.cpp #include "./test.hpp" S const & get2( ) { return s; } int j = get1().i; int main() { return 0; } Compiles and links just fine, crashes and burns even before entering main(). -- Eric Niebler Boost Consulting www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Eric Niebler wrote:
Compiles and links just fine, crashes and burns even before entering main().
Understood. Thanks a lot. My next concern is how to forbid such usage with the shortest words. If msvc can't static-initialize the solution using 'static_const<>', the upcoming <boost/numeric/functional.hpp> seems to have to document the dangerous usage. Regards, -- Shunsuke Sogame

on Fri Jun 15 2007, shunsuke <pstade.mb-AT-gmail.com> wrote:
Eric Niebler wrote:
Compiles and links just fine, crashes and burns even before entering main().
Understood. Thanks a lot. My next concern is how to forbid such usage with the shortest words. If msvc can't static-initialize the solution using 'static_const<>', the upcoming <boost/numeric/functional.hpp> seems to have to document the dangerous usage.
If the types you're initializing really don't have any useful content (like boost/parameter/keyword's, which are just initialized with ={}), you can probably ignore MSVC's bug. On the platforms targeted by that compiler, the undefined behavior will express itself as the program working perfectly. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

on Fri Jun 15 2007, Eric Niebler <eric-AT-boost-consulting.com> wrote:
'Fraid not. And the Boost.Parameter trick looks like this, IIRC:
type const &name = get_static_local<type>();
Not anymore: template <class Tag> keyword<Tag> const keyword<Tag>::instance = {}; see boost/parameter/keyword.hpp -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

Sebastian Redl wrote:
Arkadiy Vertleyb wrote:
The main problem of unnamed namespaces in headers is the possibility of ODR violation. Has anyone seen any compiler complain about this?
Not this case specifically, although I've seen complaints about more obvious violations of the ODR, e.g. when you try to link against two versions of the CRT in Visual C++. (Typically because you specify one and a static library you include has another in its dependencies.)
The reason it detects this is #defines not actual ODR code violations. The tools are not there yet sadly. This would require work on the linkers to detect ODR problems, I do not see how the compiler could detect them. At least not in a single pass, perhaps not even with multiple passes ?
Now, I don't know if this is an appropriate topic here, but I would question the usefullness of the ODR itself.
The ODR is a logical necessity, not a feature that may be useful or not. If the compiler generates two differing definitions of a symbol, how can the linker possibly know which one to use? And if it doesn't know which one to use, how can the program have defined behaviour? A better question would be whether to relax the ODR such that "equivalent" (under specific rules) multiple definitions do not cause the ODR to be violated, similar to what is already done for template instantiations.
I agree.
My main problem with it -- it contradicts to quite useful, IMO, idiom, where a library author defines a main template in his/her library as a customization point, and the users provide specializations of this template (similar to virtual functions in runtime world).
What does this have to do with the ODR?
Sebastian Redl His last point is very unclear to me. Perhaps he could clarify so we understand.
I think the point here is that it is very possible to introduce bugs and/or side effects from using these unnamed namespaces in headers.. Like any other language construct it has its uses but is also easily abused. Anonymous namespaces need to only be used after careful consideration of the consequences. Best regards, Richard Day

Richard Day wrote:
The reason it detects this is #defines not actual ODR code violations.
No, I'm pretty sure the Microsoft linker simply always complains when two static libraries contain the same symbol. I know that the errors I get in the case I described are linker errors, not compiler errors. Sebastian Redl

Sebastian Redl wrote:
Richard Day wrote:
The reason it detects this is #defines not actual ODR code violations.
No, I'm pretty sure the Microsoft linker simply always complains when two static libraries contain the same symbol. I know that the errors I get in the case I described are linker errors, not compiler errors.
Sebastian Redl Never having tried it personally I will take your word for it. It makes sense anyway. Basically what I am saying is that detecting these ODR violations seems to require linker modifications. Something that microsoft purportedly intends to fix by modifying their tools. They are aware of the issues it would seem. See http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violat...
Best regards, Richard Day

on Thu Jun 14 2007, "Arkadiy Vertleyb" <vertleyb-AT-hotmail.com> wrote:
"Richard Day" <richardvday@verizon.net> wrote
Basically if boost is striving for header only libraries when ever possible(And that is my impression)
I don't think this is 100% correct. In my impression Boost is a combinatiom of libraries produced by different people (or different groups of people). Each library author has his/her only preference regarding splitting the code between headers and source files.
should there be unnamed namespace's being used at all ?
The main problem of unnamed namespaces in headers is the possibility of ODR violation. Has anyone seen any compiler complain about this? In Typeof library we specifically implement test cases to cause ODR violation (because we do use unnamed namespaces in headers; only since they are hidden inside macro definitions, we don't get inspection complains). No compiler complains of any ODR so far.
I'm less worried about ODR being diagnosed than I am about undiagnosed ODR violations causing code to misbehave. The effects could be subtle, like two identical specializations of the same function template ending up with different addresses. The linker could refuse to merge them because the body of the generated code is different, which would have happened because the two identical specializations used different instances objects from unnamed namespaces (e.g. _1). So I'm not convinced that testing to see if the compiler complains is enough. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

"Guillaume Melquiond" <guillaume.melquiond@ens-lyon.fr> wrote in message news:1181463514.3871.10.camel@liege.msr-inria.inria.fr... I don't mean in general either. The example I give you is based on your very own files. They contain unnamed namespaces used from inline functions, hence they are not compliant with the C++ standard.
For example, see the token_iterator.hpp file detected by the inspection reports. The keep_empty_tokens variable is defined in an unnamed namespace but used in an inline function, so the one that is passed as an argument to the function may not be identical to the one the function tests for.
After rereading this whole thread, I am still unclear: what is a proper way to implement there stateless keywords? Also I believe in many other places I am using type& within unnamed namespace. This seems to be valid usage, right? Gennadiy

on Sat Jun 23 2007, "Gennadiy Rozental" <gennadiy.rozental-AT-thomson.com> wrote:
After rereading this whole thread, I am still unclear: what is a proper way to implement there stateless keywords?
look at boost/parameter/keyword.hpp
Also I believe in many other places I am using type& within unnamed namespace. This seems to be valid usage, right?
You've left out too much detail for me to make a determination. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:87vede48j6.fsf@grogan.peloton...
on Sat Jun 23 2007, "Gennadiy Rozental" <gennadiy.rozental-AT-thomson.com> wrote:
After rereading this whole thread, I am still unclear: what is a proper way to implement there stateless keywords?
look at boost/parameter/keyword.hpp
Will do.
Also I believe in many other places I am using type& within unnamed namespace. This seems to be valid usage, right?
You've left out too much detail for me to make a determination.
This is essentially boost/test/trivial_singleton.hpp: #define BOOST_TEST_SINGLETON_INST( inst ) \ namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); } Here inst ## _t is type of singleton and inst is a reference to the instance Gennadiy

on Sat Jun 23 2007, "Gennadiy Rozental" <gennadiy.rozental-AT-thomson.com> wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:87vede48j6.fsf@grogan.peloton...
on Sat Jun 23 2007, "Gennadiy Rozental" <gennadiy.rozental-AT-thomson.com> wrote:
After rereading this whole thread, I am still unclear: what is a proper way to implement there stateless keywords?
look at boost/parameter/keyword.hpp
Will do.
Also I believe in many other places I am using type& within unnamed namespace. This seems to be valid usage, right?
You've left out too much detail for me to make a determination.
This is essentially boost/test/trivial_singleton.hpp:
#define BOOST_TEST_SINGLETON_INST( inst ) \ namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); }
Here inst ## _t is type of singleton and inst is a reference to the instance
If your question is whether you are allowed to use references inside unnamed namespaces, the answer is yes. I note that you are still using dynamic initialization above. Using brace-initialization is important to avoid order-of-initialization problems. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com The Astoria Seminar ==> http://www.astoriaseminar.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:871wg12mia.fsf@grogan.peloton...
#define BOOST_TEST_SINGLETON_INST( inst ) \ namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); }
Here inst ## _t is type of singleton and inst is a reference to the instance
If your question is whether you are allowed to use references inside unnamed namespaces, the answer is yes.
I note that you are still using dynamic initialization above. Using brace-initialization is important to avoid order-of-initialization problems.
I will look into your solution. In my projects it's not usually the problem. If I need to refer to one singleton from different singleton constructor I always use type::instance(). Gennadiy
participants (14)
-
"JOAQUIN LOPEZ MU?Z"
-
Arkadiy Vertleyb
-
Bryan Ewbank
-
David Abrahams
-
Douglas Gregor
-
Eric Niebler
-
Gennadiy Rozental
-
Giovanni Piero Deretta
-
Guillaume Melquiond
-
Peter Dimov
-
Rene Rivera
-
Richard Day
-
Sebastian Redl
-
shunsuke