C++ requires子句中不允许哪些替换失败?

C++ requires子句中不允许哪些替换失败?,c++,language-lawyer,c++20,c++-concepts,C++,Language Lawyer,C++20,C++ Concepts,如果所有模板参数都是唯一的,我试图编写一个返回true的函数 伪代码: template<typename... Ts> auto types_are_unique() -> bool { return (no two Ts are the same); } gcc和clang都认为这无法编译,因为唯一。cpp:7:8:错误:重复的基类型“X”无效 这是一个惊喜,阅读 将模板参数替换为模板化实体声明中使用的requires表达式可能会导致在其需求中形成无效类型或表达式,或

如果所有模板参数都是唯一的,我试图编写一个返回true的函数

伪代码:

template<typename... Ts>
auto types_are_unique() -> bool {
  return (no two Ts are the same);
}
gcc和clang都认为这无法编译,因为
唯一。cpp:7:8:错误:重复的基类型“X”无效

这是一个惊喜,阅读

将模板参数替换为模板化实体声明中使用的requires表达式可能会导致在其需求中形成无效类型或表达式,或者违反这些需求的语义约束。在这种情况下,requires表达式的计算结果为false,不会导致程序格式错误

叮当声和gcc错了吗?或者是引用错误?或者(很可能)我读错了吗

哪些类别的替换失败不允许出现在
requires
表达式中?请参考C++20当前草案的相应部分

在requires表达式中不允许出现哪类替换失败

和其他地方一样。这实际上并不特定于概念。下面是示例的一个稍加修改的版本,它演示了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>()));
使用size_t=decltype(sizeof(0));
模板
结构X{};
模板
结构测试:X。。。{};
模板结构类型列表{};
模板
constexpr自动类型是唯一的(类型列表)->bool{
返回true;
}
constexpr自动类型是唯一的(…)->bool{
返回false;
}
//嗯
静态断言(类型是唯一的(typelist());
//编译错误
静态断言(不是唯一的类型(typelist());
这个问题与替代的直接内容有关,也与替代的直接内容无关。这是一个在中引入的术语,但并未完全定义†:

如果替换导致无效的类型或表达式,则类型推断将失败。无效类型或表达式是一种格式错误的类型或表达式,如果使用替换参数编写,则需要诊断。[注:如果不需要诊断,则程序仍然格式不正确。访问检查作为替换过程的一部分进行。-结束注]只有函数类型、其模板参数类型及其显式说明符的直接上下文中的无效类型和表达式才能导致扣减失败。[注:替换为类型和表达式可能导致诸如类模板专门化和/或函数模板专门化的实例化、隐式定义函数的生成等效果。此类效果不在“即时上下文”中,可能导致程序格式错误。-结束注]

一般的想法是,只有声明中的失败才会导致替换失败,而定义中的失败会导致导致程序格式错误的硬错误。在这里的示例中,问题不在于
Test
的声明,而在于它的定义(在我们到达它的基类的时候).而这被认为为时已晚-直接环境之外的失败不再是替代失败



†我们甚至有一个核心问题()要求更好的定义。

硬错误与软错误…你能告诉我标准草案中的
requires
表达式的区别在哪里吗?感谢你的解释和核心问题的链接!有了这种模糊性,我很惊讶SFINAE在编译器之间的一致性。。。
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>()));