https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65942
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |ASSIGNED
Component|c++ |libstdc++
--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Further reduced:
template<typename _Tp>
_Tp&& declval() noexcept;
template<typename Arg>
struct function
{
template<typename Functor,
typename = decltype( declval<Functor&>()(declval<Arg>()) )>
function(Functor) { }
function() { }
bool operator()(Arg) const;
};
template<typename Compare>
struct Iter_comp
{
Compare m_comp;
Iter_comp(Compare comp)
: m_comp(comp)
{ }
template<typename Iterator>
#ifndef OK
constexpr
#endif
bool
operator()(Iterator it) const
{ return m_comp(*it); }
};
using F = function<int>;
F f;
Iter_comp<F> c{ f };
auto c2 = c;
GCC says:
f.cc: In instantiation of ‘constexpr bool
Iter_comp<Compare>::operator()(Iterator) const [with Iterator = int; Compare =
function<int>]’:
f.cc:8:52: required by substitution of ‘template<class Functor, class>
function<Arg>::function(Functor) [with Functor = Iter_comp<function<int> >;
<template-parameter-1-2> = <missing>]’
f.cc:38:11: required from here
f.cc:32:23: error: invalid type argument of unary ‘*’ (have ‘int’)
{ return m_comp(*it); }
^
and Clang says:
f.cc:32:23: error: indirection requires pointer operand ('int' invalid)
{ return m_comp(*it); }
^~~
f.cc:8:35: note: in instantiation of function template specialization
'Iter_comp<function<int> >::operator()<int>' requested here
typename = decltype( declval<Functor&>()(declval<Arg>()) )>
^
f.cc:9:7: note: in instantiation of default argument for
'function<Iter_comp<function<int> > >' required here
function(Functor) { }
^~~~~~~~
f.cc:38:11: note: while substituting deduced template arguments into function
template 'function' [with Functor = Iter_comp<function<int> >, $1 = (no value)]
auto c2 = c;
^
1 error generated.
What I don't understand is why function<int>::function<Comp_iter<function<int>>
ever gets considered for overload resolution. Where does that come from and
why?
Anyway, it seems we can fix the library by constraining
_Iter_comp_iter::operator()
template<typename Iterator, typename =
decltype(declval<Compare&>()(*declval<Iterator>()))>
#ifndef OK
constexpr
#endif
bool
operator()(Iterator it) const
{ return m_comp(*it); }
That prevents it being instantiated as a possible argument to std::function.
Changing component back to libstdc++