假设我有一个类/结构模板及其构造函数的显式推导指南。让这个类有两个模板参数,一个可以由推导指南推导,另一个不能。
template <int Q, typename T>
struct Foo {
template <typename F>
Foo(F&&) { }
};
template <typename T>
using alias = T;
template <typename T>
struct alias2 { using type = T; };
template <int Q, typename F>
Foo(F&& f) -> Foo<Q, alias<F>>; // deduction guide, but cannot deduce Q yet
template <typename T>
using Bar = Foo<1, T>; // create alias that fixes Q
/* This should generate a deduction guide for Bar<T> by first
"copying" Foo's deduction guide, deducing from Foo<Q, alias<F>>
and Foo<1, T> that Q=1 and T=alias<F>=F, thus generating
<template F>
Bar(F&&) -> Bar<1, F>;
if this was correct syntax. */
int main() {
Bar f{ 5 };
}
如果我现在创建一个别名,它将显式指定以前不可推导的参数,据我所知,这个别名的隐式生成的推导指南应该能够完全推导两个模板参数(通过标准模板参数推导的规则),即使在定义类模板中未推断出一种类型。
但是在我不使用alias
但是的情况下我该怎么办alias2
,即将扣除指南更改为
template <int Q, typename F>
Foo(F&& f) -> Foo<Q, typename alias2<F>::type>;
根据文档,现在这将引入一个非推导上下文(因为模板参数出现在范围运算符的左侧::
),因此模板参数推导T=F
应该失败(显然会失败)。
问题1:如果这个理论是正确的,我能做些什么吗?假设我不想使用微不足道的身份别名,而是使用更复杂的类型转换,最终将typename transformation<Input>::result
在演绎指南中具有 a 的形状。
问题 2:即使是现在,当我完全删除 Q 时,我的理论仍然失败,因为以下代码将被接受(通过 GCC-10/11):
template <typename T>
struct Foo {
template <typename F>
Foo(F&&) { }
};
template <typename T>
struct alias2 { using type = T; };
template <typename F>
Foo(F&& f) -> Foo<typename alias2<F>::type>;
template <typename T>
using Bar = Foo<T>;
template <typename T>
void some(typename alias2<T>::type) { }
int main() {
Bar f{ 5 };
}
为什么即使这是非推导上下文,编译器也能够从 F 推导出 T?