如果所有模板参数都是唯一的,我试图编写一个返回true的函数。
伪代码:
template<typename... Ts>
auto types_are_unique() -> bool {
return (no two Ts are the same);
}
我不是要“手动”相互比较T
,而是要使用这样的事实:如果两个或多个基类相同,则不允许多重继承。
#include <utility>
template <typename T>
struct X {};
template <typename... Ts>
struct Test : X<Ts>... {};
template <typename... Ts>
constexpr auto types_are_unique() -> bool {
return false;
}
template <typename... Ts>
requires requires { Test<Ts...>{}; }
constexpr auto types_are_unique() -> bool {
return true;
}
int main() {
static_assert(types_are_unique<int, float>()); // compiles
static_assert(not types_are_unique<int, int>()); // fails
}
gcc和clang都同意这不能编译,因为unique.cpp:7:8: error: duplicate base type ‘X<int>’ invalid
。
阅读https://en.cppreference.com/w/cpp/language/constraints#Requires_expressions,这真是令人惊讶
将模板参数替换为模板实体的声明中使用的require-表达式可能会导致其要求中形成无效的类型或表达式,或者违反这些要求的语义约束。在这种情况下,required表达式的计算结果为false,不会导致程序格式错误。
clang和gcc错误吗?还是cppreference错误?或者(很可能)我读错了吗?
requires
表达式中不允许出现哪类替换失败?请参阅C ++ 20当前草案的相应部分。
在require表达式中不允许发生哪类替换失败?
与其他任何地方一样。这实际上并不是特定于概念的。这是您的示例的稍作修改的版本,它演示了C ++ 11的相同问题:
using size_t = decltype(sizeof(0));
template <typename T>
struct X {};
template <typename... Ts>
struct Test : X<Ts>... {};
template <typename...> struct typelist { };
template <typename... T, size_t = sizeof(Test<T...>)>
constexpr auto types_are_unique(typelist<T...>) -> bool {
return true;
}
constexpr auto types_are_unique(...) -> bool {
return false;
}
// ok
static_assert(types_are_unique(typelist<int, float>()));
// compile error
static_assert(not types_are_unique(typelist<int, int>()));
该问题与替代的直接上下文中的实质有关。这是[temp.deduct] / 8中引入的一个术语,但并未真正明确定义†:
如果替换导致无效的类型或表达式,则类型推导失败。如果使用替换的参数编写,则无效的类型或表达式是格式错误的,需要进行诊断。[注意:如果不需要诊断,则程序仍然格式错误。访问检查是替代过程的一部分。—尾注]只有在函数类型,其模板参数类型及其显式说明符的直接上下文中的无效类型和表达式才可能导致推论失败。[注:替换为类型和表达式可能会导致诸如实例化类模板专业化和/或函数模板专业化,生成隐式定义的函数等效果。此类效果不在“立即上下文”中,并且可以导致程序格式错误。—尾注]
通常的想法是,仅声明中的失败会导致替换失败,而定义中的失败会导致硬错误,这些错误会导致程序格式错误。在这里的示例中,问题不在于Test<int, int>
它的定义中的声明(在我们到达其基类的时候)。这被认为为时已晚-即时上下文之外的失败不再是替代失败。
†我们甚至有一个核心问题(1844),要求更好的定义。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句