与 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_from
的 validity 而不会对其进行评估,你应该使用 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>;
请注意,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
(问题源于玩弄概念;不要将此视为相应的工程选择或其他任何东西。)
我试图指定满足概念的类型必须具有成员类型,并且该成员类型必须可以某种方式构造。作为一个最小的例子,它必须可以从 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_from
的 validity 而不会对其进行评估,你应该使用 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>;
请注意,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