
The following code doesn't compile on gcc 3.3.5 typedef int (fun)(bool); fun& foo(); BOOST_STATIC_ASSERT((boost::is_same<BOOST_TYPEOF(foo()), fun>::value)); The error is error: no matching function for call to `ensure_obj(int(&)(bool))' This can be fixed by introducing more specialized ensure_obj: template<class T> T& ensure_obj(const T&, int); template<class R, class T0> R(& ensure_obj(R (&)(T0), ...) )(T0); template<class R, class T0, class T1> R(& ensure_obj(R (&)(T0,T1), ...) )(T0,T1); // ... ( second argument is not required for gcc 3.3.5, it's there to resolve ambuiguity on other compilers ) This fix has been tested on three different compilers:
~/pkgsrc-root/gcc3/bin/g++ -v Reading specs from /home/alnsn/pkgsrc-root/gcc3/lib/gcc-lib/i386-pc-freebsd6/3.3.5/specs Configured with: ./configure --prefix=/home/alnsn/pkgsrc-root/gcc3 --host=i386-pc-freebsd6 --enable-shared --enable-languages=c++ Thread model: posix gcc version 3.3.5
g++ -v Using built-in specs. Configured with: FreeBSD/i386 system compiler Thread model: posix gcc version 3.4.4 [FreeBSD] 20050518
/usr/local/intel_cc_80/bin/icpc -v -V Intel(R) C++ Compiler for 32-bit applications, Version 8.1 Build 20050207Z Package ID: l_cc_pc_8.1.028 Copyright (C) 1985-2005 Intel Corporation. All rights reserved. FOR NON-COMMERCIAL USE ONLY
Version 8.1 Also, other contexts mentioned by Arkadiy in other thread should be modified. BTW, why test/function_ref.cpp checks only test_wrapper type, not a function reference? -- Alexander Nasonov

Alexander Nasonov wrote:
The following code doesn't compile on gcc 3.3.5
typedef int (fun)(bool); fun& foo();
BOOST_STATIC_ASSERT((boost::is_same<BOOST_TYPEOF(foo()), fun>::value));
The error is
error: no matching function for call to `ensure_obj(int(&)(bool))'
This can be fixed by introducing more specialized ensure_obj:
template<class T> T& ensure_obj(const T&, int); template<class R, class T0> R(& ensure_obj(R (&)(T0), ...) )(T0); template<class R, class T0, class T1> R(& ensure_obj(R (&)(T0,T1), ...) )(T0,T1); // ...
Sorry for jumping in here. But I believe that #ifndef BOOST_NO_SFINAE namespace boost { namespace type_of { template<typename T> typename enable_if<is_function<T>, T &>::type ensure_obj(T &); } } #endif // verified to solve the problem with GCC 3.2.3 is a much nicer solution to the problem you describe (because it leaves scalability up to boost::is_function). Best, Tobias

Tobias Schwinger wrote:
Sorry for jumping in here. But I believe that
#ifndef BOOST_NO_SFINAE namespace boost { namespace type_of { template<typename T> typename enable_if<is_function<T>, T &>::type ensure_obj(T &); } } #endif // verified to solve the problem with GCC 3.2.3
is a much nicer solution to the problem you describe (because it leaves scalability up to boost::is_function).
Unfortunately, this doesn't compile neither on gcc 3.3.x nor on gcc 3.2.3. BTW, my solution doesn't compile on gcc 4.0: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [...] Correct fix is namespace boost { namespace type_of { template<class T> T& ensure_obj(const T&); #if defined(__GNUC__) && __GNUC__ == 3 && \ ((__GNUC_MINOR__ == 2) || (__GNUC_MINOR__ == 3)) template<class R, class T0> R(& ensure_obj(R(&)(T0)) )(T0); template<class R, class T0, class T1> R(& ensure_obj(R(&)(T0,T1)) )(T0,T1); // ... // ... #endif }} -- Alexander Nasonov

Alexander Nasonov wrote:
Tobias Schwinger wrote:
Sorry for jumping in here. But I believe that
#ifndef BOOST_NO_SFINAE namespace boost { namespace type_of { template<typename T> typename enable_if<is_function<T>, T &>::type ensure_obj(T &); } } #endif // verified to solve the problem with GCC 3.2.3
is a much nicer solution to the problem you describe (because it leaves scalability up to boost::is_function).
Unfortunately, this doesn't compile neither on gcc 3.3.x nor on gcc 3.2.3.
Did you try catching T volatile & as a workaround? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8503 Well, it compiles fine on my copy of GCC (MinGW) and in MinGW 3.2.3 that bug is patched away (although it still doesn't match a function reference with T const & as GCC 3.4 does).

Tobias Schwinger wrote:
Alexander Nasonov wrote:
Tobias Schwinger wrote:
Sorry for jumping in here. But I believe that
#ifndef BOOST_NO_SFINAE namespace boost { namespace type_of { template<typename T> typename enable_if<is_function<T>, T &>::type ensure_obj(T &); } } #endif // verified to solve the problem with GCC 3.2.3
is a much nicer solution to the problem you describe (because it leaves scalability up to boost::is_function).
Unfortunately, this doesn't compile neither on gcc 3.3.x nor on gcc 3.2.3.
It didn't compile because I included enable_if.hpp and is_function.hpp only for emulation mode. Now your code compiles fine. -- Alexander Nasonov

"Alexander Nasonov" <alnsn@yandex.ru> wrote
Tobias Schwinger wrote: [...]
It seems that recently discovered problems in typeof all have the same origin: [some compilers][in some contexts] can't bind some types to const T& The remedy seems to be to add overload(s) that handle this particular case. It also looks such overloads should be added on per-compiler basis, otherwise new problems may be introduced. As was mentioned before, if such a problem exists, it exists in 4 contexts: 1) ensure_obj (native typeof wrapping); 2) typeof emulation; 3) MSVC typeof trick; 4) LVALUE_TYPEOF. I am afraid that it all in 4 places will pollute the code with compiler-specific workarounds... OTOH, it looks like all the workarounds just define _additional_ overloads. So what if we add a separate header for every "broken" compiler? Such headers would have all the additional overloads, possibly #ifdeffed by the compiler version, and #included during configuration? Thoughts? Regards, Arkadiy

Arkadiy Vertleyb wrote:
OTOH, it looks like all the workarounds just define _additional_ overloads. So what if we add a separate header for every "broken" compiler? Such headers would have all the additional overloads, possibly #ifdeffed by the compiler version, and #included during configuration?
Looks fine to me. -- Alexander Nasonov

Alexander Nasonov wrote:
Tobias Schwinger wrote:
Sorry for jumping in here. But I believe that
#ifndef BOOST_NO_SFINAE namespace boost { namespace type_of { template<typename T> typename enable_if<is_function<T>, T &>::type ensure_obj(T &); } } #endif // verified to solve the problem with GCC 3.2.3
[skiped]
It didn't compile because I included enable_if.hpp and is_function.hpp only for emulation mode. Now your code compiles fine.
I added int foo(bool); BOOST_STATIC_ASSERT(( boost::is_same<BOOST_TYPEOF(foo), int(bool)>::value )); to the end of libs/typeof/test/function.cpp and typedef int (fun)(bool); fun &foo(); BOOST_STATIC_ASSERT(( boost::is_same<BOOST_TYPEOF(foo()), fun>::value )); to the end of libs/typeof/test/function_ref.cpp The code written by Tobias fixes function_native and function_ref_native tests on gcc 3.2.3 and 3.3.6. It doesn't break any test on gcc 3.4.4. On gcc 4.0.3 and gcc 4.2.0, it fixes lvalue_native test. I haven't tried to analyze why, though. lvalue_native error report on gcc 4.0.2 can be found here: http://tinyurl.com/7oemg -- Alexander Nasonov

"Alexander Nasonov" <alnsn@yandex.ru> wrote
BTW, why test/function_ref.cpp checks only test_wrapper type, not a function reference?
It just tests if function references can be encoded/decoded correctly. This is what the test<> template does. It wrapps types to ignore the issue of top-level consts/references. Regards, Arkadiy
participants (3)
-
Alexander Nasonov
-
Arkadiy Vertleyb
-
Tobias Schwinger