return operand;
}
+/* True iff CONV represents a conversion sequence which no other can be better
+ than under [over.ics.rank]: in other words, a "conversion" to the exact same
+ type (including binding to a reference to the same type). This is stronger
+ than the standard's "identity" category, which also includes reference
+ bindings that add cv-qualifiers or change rvalueness. */
+
+static bool
+perfect_conversion_p (conversion *conv)
+{
+ if (CONVERSION_RANK (conv) != cr_identity)
+ return false;
+ if (!conv->rvaluedness_matches_p)
+ return false;
+ if (conv->kind == ck_ref_bind
+ && !same_type_p (TREE_TYPE (conv->type),
+ next_conversion (conv)->type))
+ return false;
+ return true;
+}
+
+/* True if CAND represents a perfect match, i.e. all perfect conversions, so no
+ other candidate can be a better match. Since the template/non-template
+ tiebreaker comes immediately after the conversion comparison in
+ [over.match.best], a perfect non-template candidate is better than all
+ templates. */
+
+static bool
+perfect_candidate_p (z_candidate *cand)
+{
+ if (cand->viable < 1)
+ return false;
+ int len = cand->num_convs;
+ for (int i = 0; i < len; ++i)
+ if (!perfect_conversion_p (cand->convs[i]))
+ return false;
+ if (conversion *conv = cand->second_conv)
+ if (!perfect_conversion_p (conv))
+ return false;
+ return true;
+}
+
/* Add each of the viable functions in FNS (a FUNCTION_DECL or
OVERLOAD) to the CANDIDATES, returning an updated list of
CANDIDATES. The ARGS are the arguments provided to the call;
/* Delay creating the implicit this parameter until it is needed. */
non_static_args = NULL;
+ /* If there's a non-template perfect match, we don't need to consider
+ templates. So check non-templates first. This optimization is only
+ really needed for the defaulted copy constructor of tuple and the like
+ (96926), but it seems like we might as well enable it more generally. */
+ bool seen_perfect = false;
+ enum { templates, non_templates, either } which = either;
+ if (template_only)
+ which = templates;
+ else /*if (flags & LOOKUP_DEFAULTED)*/
+ which = non_templates;
+
+ again:
for (lkp_iterator iter (fns); iter; ++iter)
{
fn = *iter;
continue;
if (check_list_ctor && !is_list_ctor (fn))
continue;
+ if (which == templates && TREE_CODE (fn) != TEMPLATE_DECL)
+ continue;
+ if (which == non_templates && TREE_CODE (fn) == TEMPLATE_DECL)
+ continue;
tree fn_first_arg = NULL_TREE;
const vec<tree, va_gc> *fn_args = args;
fn,
ctype,
explicit_targs,
- fn_first_arg,
+ fn_first_arg,
fn_args,
return_type,
access_path,
flags,
strict,
complain);
- else if (!template_only)
- add_function_candidate (candidates,
- fn,
- ctype,
- fn_first_arg,
- fn_args,
- access_path,
- conversion_path,
- flags,
- NULL,
- complain);
+ else
+ {
+ add_function_candidate (candidates,
+ fn,
+ ctype,
+ fn_first_arg,
+ fn_args,
+ access_path,
+ conversion_path,
+ flags,
+ NULL,
+ complain);
+ if (perfect_candidate_p (*candidates))
+ seen_perfect = true;
+ }
+ }
+ if (which == non_templates && !seen_perfect)
+ {
+ which = templates;
+ goto again;
}
}
--- /dev/null
+// PR c++/96926
+// { dg-do compile { target c++11 } }
+
+namespace std
+{
+ template<typename _Tp, _Tp __v>
+ struct integral_constant
+ {
+ static constexpr _Tp value = __v;
+ typedef integral_constant<_Tp, __v> type;
+ };
+
+ template<typename _Tp, _Tp __v>
+ constexpr _Tp integral_constant<_Tp, __v>::value;
+
+ typedef integral_constant<bool, true> true_type;
+ typedef integral_constant<bool, false> false_type;
+
+ template<bool __v>
+ using bool_constant = integral_constant<bool, __v>;
+
+ template<bool, typename, typename>
+ struct conditional;
+
+ template<typename...>
+ struct __and_;
+
+ template<>
+ struct __and_<>
+ : public true_type
+ { };
+
+ template<typename _B1>
+ struct __and_<_B1>
+ : public _B1
+ { };
+
+ template<typename _B1, typename _B2>
+ struct __and_<_B1, _B2>
+ : public conditional<_B1::value, _B2, _B1>::type
+ { };
+
+ template<typename _B1, typename _B2, typename _B3, typename... _Bn>
+ struct __and_<_B1, _B2, _B3, _Bn...>
+ : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
+ { };
+
+ template<typename _Tp, typename... _Args>
+ struct is_constructible
+ : public bool_constant<__is_constructible(_Tp, _Args...)>
+ {
+ };
+
+ template<bool, typename _Tp = void>
+ struct enable_if
+ { };
+
+ template<typename _Tp>
+ struct enable_if<true, _Tp>
+ { typedef _Tp type; };
+
+ template<bool _Cond, typename _Tp = void>
+ using __enable_if_t = typename enable_if<_Cond, _Tp>::type;
+
+ template<bool _Cond, typename _Iftrue, typename _Iffalse>
+ struct conditional
+ { typedef _Iftrue type; };
+
+
+ template<typename _Iftrue, typename _Iffalse>
+ struct conditional<false, _Iftrue, _Iffalse>
+ { typedef _Iffalse type; };
+
+
+ template<bool, typename... _Types>
+ struct _TupleConstraints
+ {
+ template<typename... _UTypes>
+ static constexpr bool __is_implicitly_constructible()
+ {
+ // is_constructible is incomplete here, but only when
+ // it is also instantiated in __is_explicitly_constructible
+ return __and_<is_constructible<_Types, _UTypes>...,
+ true_type
+ >::value;
+ }
+
+ template<typename... _UTypes>
+ static constexpr bool __is_explicitly_constructible()
+ {
+#if FIX
+ return false;
+#else
+ return __and_<is_constructible<_Types, _UTypes>...,
+ false_type
+ >::value;
+#endif
+ }
+ };
+
+ template<typename... _Elements>
+ class tuple
+ {
+ template<bool _Cond>
+ using _TCC = _TupleConstraints<_Cond, _Elements...>;
+
+ template<bool _Cond, typename... _Args>
+ using _ImplicitCtor = __enable_if_t<
+ _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
+ bool>;
+
+ template<bool _Cond, typename... _Args>
+ using _ExplicitCtor = __enable_if_t<
+ _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
+ bool>;
+
+ public:
+
+ template<bool _NotEmpty = true,
+ _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
+ constexpr
+ tuple(const _Elements&... __elements)
+ { }
+
+ template<bool _NotEmpty = true,
+ _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
+ explicit constexpr
+ tuple(const _Elements&... __elements)
+ { }
+ };
+}
+
+// first example
+
+template <typename SessionT>
+struct SomeQuery {
+ SessionT& session_;
+ SomeQuery(SessionT& session) : session_(session) {}
+};
+
+template <typename SessionT>
+struct Handler {
+ std::tuple<SomeQuery<SessionT>> queries_;
+ Handler(SessionT& session) : queries_(session) {}
+};
+
+struct Session {
+ Handler<Session> handler_;
+ Session() : handler_{*this} {}
+};
+
+int main() {
+ Session session;
+}
+static_assert(std::is_constructible<SomeQuery<Session>, const SomeQuery<Session>&>::value, "");
+
+// second example
+
+template <typename T>
+class DependsOnT
+{
+public:
+ DependsOnT(T&) {}
+};
+
+class Test
+{
+public:
+ Test() : test_{*this} {}
+
+private:
+ std::tuple<DependsOnT<Test>> test_;
+};
+static_assert(std::is_constructible<DependsOnT<Test>, const DependsOnT<Test>&>::value, "");