- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个类/结构模板及其构造函数的显式推导指南。让这个类有两个模板参数,其中一个可以通过推导指南推导,另一个不能。
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 };
}
如果我现在创建一个别名来明确指定以前不可推导的参数,as far as I understand ,此别名的隐式生成推导指南应该能够完全推导两个模板参数(根据标准模板参数推导规则),即使在定义类模板中未推导一种类型。
但是在不使用alias
的场景下怎么办呢? ,但是 alias2
,即将推导指南改为
template <int Q, typename F>
Foo(F&& f) -> Foo<Q, typename alias2<F>::type>;
根据documentation ,这现在将引入一个非推导上下文(因为模板参数出现在范围运算符 left 中 ::
),因此 T=F
的模板参数推导应该会失败(显然是 does )。
问题 1:如果这个理论是正确的,我能做些什么吗?假设我不想使用一个普通的身份别名,而是一个更复杂的类型转换,最终将具有 typename transformation<Input>::result
的形状。在演绎指南中。
问题 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,即使这是一个非推导上下文?
最佳答案
要执行您想要的操作,C++ 必须能够反转图灵完备的子程序。
图灵完备程序不仅不可逆,而且无法确定给定的图灵完备程序是否可逆。您可以定义可逆的子语言,但这些子语言缺乏图灵完备的能力。
推导 Bar
别名参数:
template <typename T>
using Bar = Foo<1, T>;
需要反转第二个模板参数 alias<F>
寻找F
.当alias
是一个简单的模板别名,这是 C++ 标准可能、允许和要求的。
当 alias2
评估是一个 foo<F>::type
,这样的构造能够进行图灵完备的计算。 C++ 标准统一表示“不要尝试”,而不是让编译器尝试 反转这样的计算。它通常使用“依赖类型”来阻止这种反转尝试。
在你的第二种情况下,Bar
是 Foo
的普通别名. Foo
有推导指南。该推导指南告诉我们如何从 F
得到至 T
,因此编译器不必反转任何可能的图灵完备程序来确定 T
.
C++ 语言有一堆措辞允许只是重命名参数等的模板别名就像它们是原始类型一样。本来连个玩具的别名都会挡住一堆这样的推演;但后来发现这是一个糟糕的计划。因此,他们在标准中添加了文本来描述什么样的模板别名在那里“微不足道”,并修改了推导规则的措辞,以便将它们视为透明。
为了在类型推导期间反转任意图灵完备程序(事实上,几乎任何结构上非平凡的类型转换),您必须明确给出反转。
一旦你接受了这一点,它就变成了与语法的斗争,而不是概念上的斗争。
我不知道别名模板的自定义模板推导指南的现状。上次听说它不受支持,但我最近没有检查过。
关于c++ - 如何在 C++20 中为模板别名创建推导指南?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62897107/
我是一名优秀的程序员,十分优秀!