在this code中,
template<class T, class U>
concept always_true = true;
template<class T>
concept always_true_if_tagged = always_true<T, typename T::tag>;
struct A {
using tag = int;
};
static_assert(always_true_if_tagged<A>);
static_assert(!always_true_if_tagged<int>); //GCC says this failed
GCC说第二个Assert失败了,Clang和MSVC都同意编译它。
我最初认为它是病态的,不需要诊断,因为temp.constr.normal#1.4
概念id C<A1, A2, ..., An>
的范式是在用A1, A2, ..., An
替换每个原子约束中的参数Map中的C
的相应模板参数之后,C
的约束表达式的范式。如果任何这样的替换导致无效类型或表达式,则程序是病态的;不需要诊断。
代换T::typename tag
是always_true
的参数Map,因此它是病态的;不需要诊断。
我的前两个问题是
1.* * 我说得对吗?(它是不是格式不对,我的理由是否正确?)
1.* * 为什么它应该是病态的?(如果我是正确的。)
解决方案之一是先检查嵌套的类型名,这样always_true
的参数Map就不会发生。
template<class T>
concept always_true_if_tagged =
requires {typename T::tag;}
&& always_true<T, typename T::tag>;
此外,温度结构原子#3表示
若要确定是否满足原子约束,首先将参数Map和模板参数替换到其表达式中。**如果替换导致无效类型或表达式,则不满足约束。**否则,如有必要,将执行左值到右值转换。并且E
应该是bool
类型的常量表达式。当且仅当E
的求值结果为true
时,满足约束。如果,在程序中的不同点,对于相同的原子约束和模板自变量,满足结果是不同的,程序是病态的,不需要诊断。
如果我写
template<class T>
concept always_true_if_tagged = bool(always_true<T, typename T::tag>);
bool(always_true<T, typename T::tag>)
是一个原子约束IIUC,用T=int
替换T::typename tag
会导致类型无效,因此应该是格式良好的,不能满足。
我最后的两个(或四个)问题是
1.* * 为什么这不适用于第一个代码,或者为什么[temp.constr.normal#1.4]不适用于这里?**
- 3.1.这个替换是概念id
always_true
的参数Map吗? - 3.2.在
concept C = always_true<T, typename T::tag>
中使用always_true
是原子约束吗?temp. constr. constr #general-1说有三种不同的约束:合取、析取和原子约束。
1.* * 为什么带T=int
的concept C = always_true<T, typename T::tag>
不能像这个一样是格式良好的?**(可能与第二个问题相同)
2条答案
按热度按时间d6kp6zgx1#
首先,作用域解析操作符(::)的lhs只能是“命名空间或类、枚举或依赖类型”,否则就是格式错误。
在我的实验中,
always_true_if_tagged<int>
在gcc编译器中实际上被求值为true
,所以static_assert
失败是因为求值为false。我猜gcc编译器假设不管T, U
如何,always_true
总是true
,所以在约束规范化中优化了typename T::tag
的求值。所以我对你们问题的回答是:
1.我相信你是对的。
1.编译器不知道约束在此状态下是否满足(约束规范化),并且在概念返回true或false之前无法执行进一步的计算。
1.如上所述,我认为编译器优化了计算。
1.使用概念时发生替换,声明概念时“创建”参数Map,见下文。
1.原子约束
原子约束由表达式E和从E中出现的模板参数到涉及受约束实体的模板参数的模板参数的Map组成,称为其参数Map。
1.我相信你现在有答案了。
o2rvlv0m2#
1.你说对了吗?[...]
是的
typename T::tag
没有用[T = int]
命名一个有效的类型。1.为什么它应该是病态的?
你引用的理由是正确的。
typename int::tag
只是没有意义。在内存中,您还需要将模板专门化移动到
struct A
之下,以便在template中使用typename A::tag
。1.为什么[...]
我不相信这是合式的,因为§ 7.3.2 [conv. lval]
我没有问题的答案,只有更多的问题。
在概念中,它不是模板示例化(请参见:[temp.concept],[temp.spec],[temp.dep]),所以我不明白这怎么可能是原子约束(它是常量表达式吗?它怎么可能求值为任何值)。
clang 14.0.0 doesn’t generate warnings with
-fsanitize=undefined
on 😰另见:
SFINAE