符合条件的特殊会员功能和琐事

Yur*_*isk 7 c++ language-lawyer c++20

考虑以下代码:

#include <type_traits>

template<typename T>
concept Int = std::is_same_v<T, int>;

template<typename T>
concept Float = std::is_same_v<T, float>;

template<typename T>
struct Foo
{
    Foo() requires Int<T> = default; // #1
    Foo() requires Int<T> || Float<T> = default; // #2
};

static_assert(std::is_trivial_v<Foo<float>>);
Run Code Online (Sandbox Code Playgroud)

为了满足静态断言,Foo<float>需要是一个平凡的类型,因此,既然它是一个类类型,那就是一个平凡的类。因此,除了可以简单地复制(确实如此)之外,它还必须有一个合格的默认构造函数(并且所有此类构造函数都必须是简单的,class.prop#2 ),这是合格的特殊成员函数的特例,定义通过特殊#6

符合条件的特殊成员函数是指满足以下条件的特殊成员函数:

  • 该功能未删除,
  • 满足关联的约束([temp.constr])(如果有),并且
  • 没有同类的特殊成员函数受到更多限制([temp.constr.order])。

严格地说,Foo<float>不存在合格的默认构造函数,因为#1不满足 的约束,并且#2存在更受约束的默认构造函数 ( #1)。因此,Foo<float>这不是一个简单的课程。但是,上面的代码可以在 gcc、clang 和 msvc ( godbolt ) 上成功编译。直觉上,它可能应该是,但是,似乎上面定义的第三个子句应该是

  • 没有满足关联约束(如果有)的同类特殊成员函数受到更多约束([temp.constr.order])

允许#2不被“遮蔽” #1(无论如何在默认构造函数的重载解析期间永远不会被选择Foo<float>)并变得合格,使得(由于是微不足道的并且只有一个合格的)变得Foo<float>微不足道。

那么我的分析正确吗?如果是这样,这是编译器错误还是上述子句的措辞不精确并且实际上暗示了我的版本?

Bar*_*rry 4

那么我的分析正确吗?

确实。我在P0848中编写此措辞的意图非常#2符合条件 - 这是重载决议会选择的一个并且它不会被删除,因此它应该符合条件。

我打开了一个CWG 问题请求,现在是CWG 2595