Причина, по которой ваш подход потерпит неудачу, заключается в том, что Predicate<T>>
в третьем параметре шаблона представляет собой , а не не выводимый контекст.Это приводит к непосредственному отказу в выводе (см. [temp.alias] / 2 ) вместо использования аргументов выведенного шаблона из других источников, как в не выводимом контексте.
Вы можете перенестиваш Predicate<T>>
в не выведенный контекст, чтобы заставить его работать:
template<class T>
struct identity {
using type = T;
};
template <template <typename...> class Predicate, typename T>
struct Resolve<Predicate, T, typename identity<Predicate<T>>::type> : std::true_type {};
Live Demo
Потому что в невыбранном контексте вычет выиграл 'Это может произойти для Predicate<T>
части, вместо этого он будет использовать Predicate
и T
, полученные из других источников.
Что касается обычного определения обнаружения (см. Ответ Гийома Рашико ) будет работать, потому что std::void_t
в качестве псевдонима шаблона будет заменен на void
в фазе удержания (см. [temp.alias] / 2 ), таким образом, нетпроизойдет удержание.
Вот несколько примеров, чтобы проиллюстрировать это более четко:
template<class T>
using always_int = int;
template<template<class> class TT>
struct deductor {};
template<template<class> class TT, class T>
void foo(T, deductor<TT>) {}
template<template<class> class TT, class T>
void bar(T, deductor<TT>, TT<T>) {}
template<class T>
void baz(T, always_int<T>) {}
int main() {
// ok, both T and TT are deduced
foo(0, deductor<always_int>{});
// ERROR, TT<T> is NOT a non-deduced context, deduction failure
bar(0, deductor<always_int>{}, 0);
// ok, T is deduced, always_int<T> is replaced by int so no deduction
baz(0, 0);
}