与 C++20 概念混淆:constructible_from 成员类型约束

Confusion with C++20 concepts: constructible_from constraint on member type

(问题源于玩弄概念;不要将此视为相应的工程选择或其他任何东西。)

我试图指定满足概念的类型必须具有成员类型,并且该成员类型必须可以某种方式构造。作为一个最小的例子,它必须可以从 3 个整数构造。但我不知道如何正确表达:

#include <concepts>

template <typename T> concept Foo = requires {
  typename T::TypeLikeThreeIntegers;
  std::constructible_from<typename T::TypeLikeThreeIntegers, int, int, int>;
  // I originally wrote
  // std::constructible_from<T::TypeLikeThreeIntegers, int, int, int>;
  // but compiler (clang++-12) gave an error and suggested the typename keyword
};

struct ThreeIntegers {
  int x, y, z;
};

struct SatisfiesFoo {
  using TypeLikeThreeIntegers = ThreeIntegers;
};

static_assert(Foo<SatisfiesFoo>);
// all is good so far

struct OnlyTwoIntegers {
  int x, y;
};

struct ShouldNotSatisfyFoo {
  using TypeLikeThreeIntegers = OnlyTwoIntegers;
};

static_assert(Foo<ShouldNotSatisfyFoo>);
// I expect this to fail but it doesn't!

int main() {
  SatisfiesFoo::TypeLikeThreeIntegers v1{1, 2, 3};
  // ShouldNotSatisfyFoo::TypeLikeThreeIntegers v2{1, 2, 3}; (error)
  // would like the concept Foo to prevent such an error and give useful diagnostic
}

你的 requires 子句中的 std::constructible_from 只会检查 std::constructible_fromvalidity 而不会对其进行评估,你应该使用 extra requires 检查:

template <typename T> concept Foo = requires {
  typename T::TypeLikeThreeIntegers;
  requires std::constructible_from<typename T::TypeLikeThreeIntegers, int, int, int>;
};

但这应该足够了:

template <typename T> concept Foo = 
  std::constructible_from<typename T::TypeLikeThreeIntegers, int, int, int>;

Demo.

请注意,Clang 会 still fail because it does not implement P0960R3,因此目前 is_constructible 不适用于聚合:

struct S { int x; };
static_assert(std::is_constructible_v<S, int>); // fails only on Clang