This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/42132] New: [C++0x] SFINAE failure with cv-qualifiers
- From: "redi at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 21 Nov 2009 14:36:11 -0000
- Subject: [Bug c++/42132] New: [C++0x] SFINAE failure with cv-qualifiers
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
Consider a simplified form of std::bind that just wraps a functor and calls it,
preserving the cv-qualifiers on the wrapper:
#include <utility>
using std::declval;
template<typename Sig>
struct result_of;
template<typename Fn, typename... ArgTypes>
struct result_of<Fn(ArgTypes...)>
{
typedef decltype( declval<Fn>()( declval<ArgTypes>()... ) ) type;
};
template<typename Fn>
struct Binder
{
Fn functor;
typename result_of<Fn()>::type
call()
{
return functor();
}
typename result_of<const Fn()>::type
call() const
{
return functor();
}
typename result_of<volatile Fn()>::type
call() volatile
{
return functor();
}
typename result_of<const volatile Fn()>::type
call() const volatile
{
return functor();
}
};
struct F
{
int operator()() { return 0; }
};
int main()
{
Binder<F> b = { };
b.call();
}
This gives:
bind.cc: In instantiation of 'result_of<const F()>':
bind.cc:26:3: instantiated from 'Binder<F>'
bind.cc:52:13: instantiated from here
bind.cc:11:65: error: passing 'const F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc:11:65: error: passing 'const F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc: In instantiation of 'result_of<volatile F()>':
bind.cc:32:3: instantiated from 'Binder<F>'
bind.cc:52:13: instantiated from here
bind.cc:11:65: error: passing 'volatile F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc:11:65: error: passing 'volatile F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc: In instantiation of 'result_of<const volatile F()>':
bind.cc:38:3: instantiated from 'Binder<F>'
bind.cc:52:13: instantiated from here
bind.cc:11:65: error: passing 'const volatile F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc:11:65: error: passing 'const volatile F' as 'this' argument of 'int
F::operator()()' discards qualifiers
using:
Using built-in specs.
COLLECT_GCC=/home/jwakely/gcc/4.x/bin/g++
COLLECT_LTO_WRAPPER=/home/jwakely/gcc/4.x/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.5.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../src/gcc/configure --prefix=/n/14/jwakely/gcc/4.x
--with-mpfr=/opt/cfarm/mpfr-2.4.1 --with-gmp=/opt/cfarm/gmp-4.2.4
--enable-libstdcxx-time=rt --enable-languages=c,c++ --disable-bootstrap :
(reconfigured) ../src/gcc/configure --prefix=/n/14/jwakely/gcc/4.x
--with-mpfr=/opt/cfarm/mpfr-2.4.1 --with-gmp=/opt/cfarm/gmp-4.2.4
--enable-libstdcxx-time=rt --enable-languages=c,c++ --disable-bootstrap
Thread model: posix
gcc version 4.5.0 20091121 (experimental) (GCC)
The problem is that overload resolution for b.call() causes result_of<cv-qual
Fn>::type to be instantiated, which gives an error when "cv-qual" does not
match the cv-quals of Fn::operator()
Shouldn't SFINAE cause those invalid instantiations to be ignored, silently
removing the invalid overloads from the overload set, leaving just the one I'm
trying to call?
This is blocking my attempts to make std::bind conform to the C++0x WP,
particularly forwarding cv-quals. If g++ is right, what extra hoops do I need
to jump through to make the code above work?
I get the same result if I use decltype directly, rather than via result_of,
which is why I think this is a sfinae bug, not a problem with using result_of
here:
#include <utility>
using std::declval;
template<typename Fn>
struct Binder
{
Fn functor;
decltype( declval<Fn&>()() )
call()
{
return functor();
}
decltype( declval<const Fn&>()() )
call() const
{
return functor();
}
decltype( declval<volatile Fn&>()() )
call() volatile
{
return functor();
}
decltype( declval<const volatile Fn&>()() )
call() const volatile
{
return functor();
}
};
struct F
{
int operator()() { return 0; }
};
int main()
{
Binder<F> b = { };
b.call();
}
bind.cc: In instantiation of 'Binder<F>':
bind.cc:43:13: instantiated from here
bind.cc:17:3: error: passing 'const F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc: In instantiation of 'Binder<F>':
bind.cc:43:13: instantiated from here
bind.cc:23:3: error: passing 'volatile F' as 'this' argument of 'int
F::operator()()' discards qualifiers
bind.cc: In instantiation of 'Binder<F>':
bind.cc:43:13: instantiated from here
bind.cc:29:3: error: passing 'const volatile F' as 'this' argument of 'int
F::operator()()' discards qualifiers
N.B. tr1::bind can handle this because tr1::result_of doesn't preserve
cv-quals, which means it gives the wrong result when operator() is overloaded
for different cv qualifiers.
--
Summary: [C++0x] SFINAE failure with cv-qualifiers
Product: gcc
Version: 4.5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: redi at gcc dot gnu dot org
OtherBugsDependingO 35569
nThis:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42132