Package: libstdc++6-4.0-dev Version: 4.0.2-5 Tags: patch Good day,
It seems there is an old and thorny issue that has addled my mind for years. It relates to the changing rules in C++ regarding max and min; in early versions, it was perfectly legal to #define max or min as you please, and indeed this is a standard idiom in many C programs. When templates came in later versions of C++ this practice was "outlawed" because the C preprocessor lacks much of the enormous power that templates provide when combined within the complex type / overloading system that was finally standardized. The language became so complex that very few people could understand it in its entirety, and perhaps no part of C++ was more feared than template instantiation such as STL. In particular, the error messages generated when a template error occurs are often delocalized with respect to the originating "root cause", and usually full of many levels of difficult and technical jargon due to many nested inline template instantiations. I myself have on at least 4 occasions over the years been confused when I wound up accidentally #define'ing max or min (sometime from somebody else's C #include file) only to waste hours trying to parse the error messages that gcc provided before I remembered to look for the offending min or max. A typical error message goes like the one reported to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12221 in 2003. There you can find the history showing that the developer decided it was "beyond the scope of V3". It is an understatement to call these error messages opaque for the vast majority of users. Today I realized a simple solution to the problem. I just wrapped all the include files that use std::min or std::max with #ifdef checks to print an error message that is easier to understand in the event of an accidental definition of max or min that is contrary to the C++ standard. I modified less than two dozen files in a very generic and uncreative way. The only deviation was one place where I removed two #undef statements. The sum total effect of all this is that now whenever somebody accidentally breaks the standard by #defining min or max, they get an error message they can read. And oftentimes the rest of the distracting error messages disappear. You can see this bug for yourself using a very simple piece of code like the following: #include <iostream> #define min(a,b) ((a<b) ? (a) : (b)) #include <fstream> int main(int argc, char **argv) { return 0; } -- I have already made a patch implementing this change. I hope that it is included with a future version of libstdc++6-4.0-dev . Using it, the error messages from the above erroneous code are less than one-third the original size and substantially clearer. I would like to offer my patch as a gift to the many people who are struggling every day to get past this too-difficult puzzle as they try to compile many of their own various and interesting programs using g++. Thanks a bunch for your time. I include the patch below. Rudi Cilibrasi http://cilibrar.com/ -- diff -rNu /usr/include/c++/4.0.3/backward/algobase.h 43good/backward/algobase.h --- /usr/include/c++/4.0.3/backward/algobase.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/backward/algobase.h 2005-12-18 15:26:12.000000000 +0100 @@ -55,6 +55,13 @@ #ifndef _BACKWARD_ALGOBASE_H #define _BACKWARD_ALGOBASE_H 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #include "backward_warning.h" #include "pair.h" #include "iterator.h" @@ -88,6 +95,10 @@ // Names from ext/memory using __gnu_cxx::uninitialized_copy_n; +#endif /* min/max protection */ + +#endif + #endif /* _BACKWARD_ALGOBASE_H */ // Local Variables: diff -rNu /usr/include/c++/4.0.3/bits/deque.tcc 43good/bits/deque.tcc --- /usr/include/c++/4.0.3/bits/deque.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/deque.tcc 2005-12-18 15:28:16.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _DEQUE_TCC #define _DEQUE_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + namespace _GLIBCXX_STD { template <typename _Tp, typename _Alloc> @@ -764,4 +771,8 @@ } } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/fstream.tcc 43good/bits/fstream.tcc --- /usr/include/c++/4.0.3/bits/fstream.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/fstream.tcc 2005-12-18 15:28:45.000000000 +0100 @@ -40,6 +40,13 @@ #ifndef _FSTREAM_TCC #define _FSTREAM_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #pragma GCC system_header namespace std @@ -901,4 +908,8 @@ #endif } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/istream.tcc 43good/bits/istream.tcc --- /usr/include/c++/4.0.3/bits/istream.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/istream.tcc 2005-12-18 15:29:04.000000000 +0100 @@ -40,6 +40,13 @@ #ifndef _ISTREAM_TCC #define _ISTREAM_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #pragma GCC system_header #include <locale> @@ -1283,4 +1290,8 @@ #endif } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/locale_facets.tcc 43good/bits/locale_facets.tcc --- /usr/include/c++/4.0.3/bits/locale_facets.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/locale_facets.tcc 2005-12-18 15:29:33.000000000 +0100 @@ -36,6 +36,13 @@ #ifndef _LOCALE_FACETS_TCC #define _LOCALE_FACETS_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #pragma GCC system_header #include <limits> // For numeric_limits @@ -2756,4 +2763,8 @@ #endif } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/sstream.tcc 43good/bits/sstream.tcc --- /usr/include/c++/4.0.3/bits/sstream.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/sstream.tcc 2005-12-18 15:30:02.000000000 +0100 @@ -40,6 +40,13 @@ #ifndef _SSTREAM_TCC #define _SSTREAM_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #pragma GCC system_header #include <sstream> @@ -235,4 +242,8 @@ #endif } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/stl_algobase.h 43good/bits/stl_algobase.h --- /usr/include/c++/4.0.3/bits/stl_algobase.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/stl_algobase.h 2005-12-18 15:30:36.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _ALGOBASE_H #define _ALGOBASE_H 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #include <bits/c++config.h> #include <cstring> #include <climits> @@ -166,9 +173,6 @@ iter_swap(__a, __b); } - #undef min - #undef max - /** * @brief This does what you think it does. * @param a A thing of arbitrary type. @@ -909,4 +913,8 @@ } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/stl_algo.h 43good/bits/stl_algo.h --- /usr/include/c++/4.0.3/bits/stl_algo.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/stl_algo.h 2005-12-18 15:30:51.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _ALGO_H #define _ALGO_H 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #include <bits/stl_heap.h> #include <bits/stl_tempbuf.h> // for _Temporary_buffer #include <debug/debug.h> @@ -5161,4 +5168,8 @@ } // namespace std +#endif /* min/max protection */ + +#endif + #endif /* _ALGO_H */ diff -rNu /usr/include/c++/4.0.3/bits/stl_bvector.h 43good/bits/stl_bvector.h --- /usr/include/c++/4.0.3/bits/stl_bvector.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/stl_bvector.h 2005-12-18 15:31:05.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _BVECTOR_H #define _BVECTOR_H 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + namespace _GLIBCXX_STD { typedef unsigned long _Bit_type; @@ -947,4 +954,8 @@ }; } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/stl_deque.h 43good/bits/stl_deque.h --- /usr/include/c++/4.0.3/bits/stl_deque.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/stl_deque.h 2005-12-18 15:31:20.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _DEQUE_H #define _DEQUE_H 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #include <bits/concept_check.h> #include <bits/stl_iterator_base_types.h> #include <bits/stl_iterator_base_funcs.h> @@ -1531,4 +1538,8 @@ { __x.swap(__y); } } // namespace std +#endif /* min/max protection */ + +#endif + #endif /* _DEQUE_H */ diff -rNu /usr/include/c++/4.0.3/bits/stl_function.h 43good/bits/stl_function.h --- /usr/include/c++/4.0.3/bits/stl_function.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/stl_function.h 2005-12-18 15:31:38.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _FUNCTION_H #define _FUNCTION_H 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + namespace std { // 20.3.1 base classes @@ -891,6 +898,10 @@ } // namespace std +#endif /* min/max protection */ + +#endif + #endif /* _FUNCTION_H */ // Local Variables: diff -rNu /usr/include/c++/4.0.3/bits/streambuf.tcc 43good/bits/streambuf.tcc --- /usr/include/c++/4.0.3/bits/streambuf.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/streambuf.tcc 2005-12-18 15:31:50.000000000 +0100 @@ -40,6 +40,13 @@ #ifndef _STREAMBUF_TCC #define _STREAMBUF_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #pragma GCC system_header namespace std @@ -151,4 +158,8 @@ #endif } // namespace std +#endif /* min/max protection */ + +#endif + #endif diff -rNu /usr/include/c++/4.0.3/bits/vector.tcc 43good/bits/vector.tcc --- /usr/include/c++/4.0.3/bits/vector.tcc 2005-12-18 16:15:35.000000000 +0100 +++ 43good/bits/vector.tcc 2005-12-18 15:32:19.000000000 +0100 @@ -61,6 +61,13 @@ #ifndef _VECTOR_TCC #define _VECTOR_TCC 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + namespace _GLIBCXX_STD { template<typename _Tp, typename _Alloc> @@ -491,4 +498,8 @@ } } // namespace std +#endif /* min/max protection */ + +#endif + #endif /* _VECTOR_TCC */ diff -rNu /usr/include/c++/4.0.3/ext/codecvt_specializations.h 43good/ext/codecvt_specializations.h --- /usr/include/c++/4.0.3/ext/codecvt_specializations.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/ext/codecvt_specializations.h 2005-12-18 15:33:35.000000000 +0100 @@ -42,6 +42,13 @@ // Define this here so codecvt.cc can have _S_max_size definition. #define _GLIBCXX_USE_ENCODING_STATE 1 +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + namespace __gnu_cxx { /// @brief Extension to use icov for dealing with character encodings. @@ -503,3 +510,7 @@ { return 1; } } // namespace std +#endif /* min/max protection */ + +#endif + diff -rNu /usr/include/c++/4.0.3/ext/ropeimpl.h 43good/ext/ropeimpl.h --- /usr/include/c++/4.0.3/ext/ropeimpl.h 2005-12-18 16:15:35.000000000 +0100 +++ 43good/ext/ropeimpl.h 2005-12-18 15:33:57.000000000 +0100 @@ -45,6 +45,13 @@ * You should not attempt to use it directly. */ +#ifdef min +#error "It is illegal to #define min in C++." +#else +#ifdef max +#error "It is illegal to #define max in C++." +#else + #include <cstdio> #include <ostream> #include <bits/functexcept.h> @@ -1704,3 +1711,7 @@ // Local Variables: // mode:C++ // End: + +#endif /* min/max protection */ + +#endif -- System Information Package files: 100 /var/lib/dpkg/status release a=now 500 http://security.debian.org etch/updates/contrib Packages release o=Debian,a=testing,l=Debian-Security,c=contrib origin security.debian.org 500 http://security.debian.org etch/updates/main Packages release o=Debian,a=testing,l=Debian-Security,c=main origin security.debian.org 500 http://ftp.surfnet.nl etch/contrib Packages release o=Debian,a=testing,l=Debian,c=contrib origin ftp.surfnet.nl 500 http://ftp.surfnet.nl etch/main Packages release o=Debian,a=testing,l=Debian,c=main origin ftp.surfnet.nl Pinned packages: Shell: /bin/zsh Locale: LANG=en_US, LC_CTYPE=zh_CN.UTF-8 Linux gosu 2.6.14.2alc #4 PREEMPT Sun Dec 11 22:49:50 CET 2005 i686 GNU/Linux -- Package: libstdc++6-4.0-dev Versions: 4.0.2-5(/var/lib/apt/lists/ftp.surfnet.nl_os_Linux_distr_debian_dists_etch_main_binary-i386_Packages)(/var/lib/dpkg/status) Reverse Depends: libstdc++6-4.0-pic,libstdc++6-4.0-dev 4.0.2-5 libstdc++6-4.0-dbg,libstdc++6-4.0-dev 4.0.2-5 libgcj6-dev,libstdc++6-4.0-dev 4.0.1 lib64stdc++6-4.0-dbg,libstdc++6-4.0-dev 4.0.2-5 g++-4.0,libstdc++6-4.0-dev 4.0.2-5 Dependencies: 4.0.2-5 - gcc-4.0-base (5 4.0.2-5) g++-4.0 (5 4.0.2-5) libstdc++6 (2 4.0.2-5) libc6-dev (2 2.3.5-5) libstdc++6-4.0-doc (0 (null)) stl-manual (0 (null)) libg++27-dev (0 (null)) libg++272-dev (3 2.7.2.8-1) libstdc++2.8-dev (0 (null)) libg++2.8-dev (0 (null)) libstdc++2.9-dev (0 (null)) libstdc++2.9-glibc2.1-dev (0 (null)) libstdc++2.10-dev (3 1:2.95.3-2) libstdc++3.0-dev (0 (null)) libstdc++6-0-dev (0 (null)) libstdc++6-0-dev (0 (null)) Provides: 4.0.2-5 - libstdc++-dev Reverse Provides: -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]