有没有一种方法可以将别名模板推导为模板模板参数,同时仍保留其被推导上下文的 属性

Is there a way to deduce alias templates to template template parameter while still preserving its property of being deduced context

一段时间后,我再次发现模板的强大功能模板参数。参见例如以下片段:

template <template <class> class TT, class T>
void foo(TT<T>) {
}

template <class T>
using typer = T;

int main() {
    foo<typer>(int{});
}

别名模板作为模板 模板参数 传递给模板,并进一步用于检测模板的其他参数,因为它是推断的上下文。美女!

然而,当需要推导别名模板本身时,编译器似乎变得疯狂了:

template <template <class> class>
struct tag{};

template <template <class> class TT, class T>
void foo(tag<TT>, TT<T>) {
}

template <class T>
using typer = T;

int main() {
    foo(tag<typer>{}, int{});
}

[live demo]

编译器当然是正确的,因为 TT 可以从 tag<TT> 以及 fooTT<T> 参数中推导出来,而 int{} 不会' 将模板模板与类型参数模式匹配。有没有办法保留 T 的推导上下文,但在 TT<T> 中使 TT 非推导上下文?

P.S。我的意图是纯粹的,这只是一个理论问题,背后没有Y问题。

我认为 easier/clearer 可以这样写:

template <template <class> class TT, class T>
void foo(tag<TT>, T, std::enable_if_t< std::is_same<T,TT<T>>::value >* = 0 )

或限制较少

template <template <class> class TT, class T>
void foo_impl( tag<TT>, TT<T> ){}

template <template <class> class TT, class T>
void foo( tag<TT> a, T b ){ foo_impl<TT>( a, b ); }

作为旁注,这表明标准中声称 永远不会推导别名模板名称 的(非规范)注释有些不准确...