8

过了一会儿,我再次发现了模板模板参数的强大功能。参见例如以下片段:

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{});
}

[现场演示]

编译器当然是正确的,因为TT可以从tag<TT>以及 的TT<T> 参数中推断出来foo,并且int{}不匹配模板模板与类型参数模式。有什么方法可以保留演绎上下文,T但在其中制作TT非演绎上下文TT<T>

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

4

1 回答 1

3

我认为编写如下内容会更容易/更清晰:

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 ); }

作为旁注,这表明标准中的(非规范性)注释声称从未推断出别名模板名称有些不准确......

于 2017-10-08T12:59:10.957 回答