This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/42132] New: [C++0x] SFINAE failure with cv-qualifiers


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]