SFINAE 的内联 requires-expression,并用作 constexpr bool
Inlined requires-expression for SFINAE, and using as constexpr bool
TL;DR:我的问题是 requires {...}
可以用作标准的 constexpr bool
表达式吗?
我在标准中没有发现任何相关内容,但它简化了很多内容并产生了更清晰的代码。例如在 SFINAE 中而不是 enable_if
或一些丑陋的 typename = decltype(declval<>()...)
或其他东西,它是一个简单干净的 requires-expression.
This 是我的例子:
#include <type_traits>
struct foo { typedef int type; };
struct bar { ~bar() = delete; };
/**
* get_type trait, if T::type is valid, get_type<T>::type
* equal to T::type, else void
*/
// T::type is valid
template<typename T, bool = requires{typename T::type;}>
struct get_type : std::type_identity<typename T::type> {};
// T::type is invalid
template<typename T>
struct get_type<T, false> : std::type_identity<void> {};
/// Template alias, this is buggy on GCC 11.1 -> internal compiler error
template<typename T>
using get_type_t = typename get_type<T>::type;
// Tests
static_assert(std::is_same_v<get_type_t<foo>, int>);
static_assert(std::is_same_v<get_type_t<bar>, void>);
/**
* Destructible trait
*
* In libstdc++-v3 this is the implementation for the testing
*
* struct __do_is_destructible_impl
* {
* template <typename _Tp, typename = decltype(declval<_Tp &>().~_Tp())>
* static true_type __test(int);
*
* template <typename>
* static false_type __test(...);
* };
*/
// This is the same:
template<typename T>
struct my_destructible_impl : std::bool_constant< requires(T t) { t.~T(); } >
{};
// Tests
static_assert(my_destructible_impl<foo>::value);
static_assert(!my_destructible_impl<bar>::value);
我发现 that 如果我是正确的,它将评估为真或假:
The substitution of template arguments into a requires-expression used in a declaration of a templated entity may result in the formation of invalid types or expressions in its requirements, or the violation of semantic constraints of those requirements. In such cases, the requires-expression evaluates to false and does not cause the program to be ill-formed. The substitution and semantic constraint checking proceeds in lexical order and stops when a condition that determines the result of the requires-expression is encountered. If substitution (if any) and semantic constraint checking succeed, the requires-expression evaluates to true.
所以我想问一下 requires {...}
是否可以像我的示例一样安全地用作 constexpr bool
表达式?因为基于 cppreference.com 我不是 100% 确定,但我觉得它是并且它是用 clang 和 GCC 编译的。但是在标准中我还没有找到任何相关信息(或者我可能只是不能正确使用 ctrl+f ...)。而且我还没有发现有人像这样使用 requires-expression...
requires {...}
是一个 requires-expression 并且根据 expr.prim.req/p2 它是一个纯右值:
A requires-expression is a prvalue of type bool whose value is
described below. Expressions appearing within a requirement-body are
unevaluated operands.
所以是的,您可以在 constexpr bool
上下文中使用它。
TL;DR:我的问题是 requires {...}
可以用作标准的 constexpr bool
表达式吗?
我在标准中没有发现任何相关内容,但它简化了很多内容并产生了更清晰的代码。例如在 SFINAE 中而不是 enable_if
或一些丑陋的 typename = decltype(declval<>()...)
或其他东西,它是一个简单干净的 requires-expression.
This 是我的例子:
#include <type_traits>
struct foo { typedef int type; };
struct bar { ~bar() = delete; };
/**
* get_type trait, if T::type is valid, get_type<T>::type
* equal to T::type, else void
*/
// T::type is valid
template<typename T, bool = requires{typename T::type;}>
struct get_type : std::type_identity<typename T::type> {};
// T::type is invalid
template<typename T>
struct get_type<T, false> : std::type_identity<void> {};
/// Template alias, this is buggy on GCC 11.1 -> internal compiler error
template<typename T>
using get_type_t = typename get_type<T>::type;
// Tests
static_assert(std::is_same_v<get_type_t<foo>, int>);
static_assert(std::is_same_v<get_type_t<bar>, void>);
/**
* Destructible trait
*
* In libstdc++-v3 this is the implementation for the testing
*
* struct __do_is_destructible_impl
* {
* template <typename _Tp, typename = decltype(declval<_Tp &>().~_Tp())>
* static true_type __test(int);
*
* template <typename>
* static false_type __test(...);
* };
*/
// This is the same:
template<typename T>
struct my_destructible_impl : std::bool_constant< requires(T t) { t.~T(); } >
{};
// Tests
static_assert(my_destructible_impl<foo>::value);
static_assert(!my_destructible_impl<bar>::value);
我发现 that 如果我是正确的,它将评估为真或假:
The substitution of template arguments into a requires-expression used in a declaration of a templated entity may result in the formation of invalid types or expressions in its requirements, or the violation of semantic constraints of those requirements. In such cases, the requires-expression evaluates to false and does not cause the program to be ill-formed. The substitution and semantic constraint checking proceeds in lexical order and stops when a condition that determines the result of the requires-expression is encountered. If substitution (if any) and semantic constraint checking succeed, the requires-expression evaluates to true.
所以我想问一下 requires {...}
是否可以像我的示例一样安全地用作 constexpr bool
表达式?因为基于 cppreference.com 我不是 100% 确定,但我觉得它是并且它是用 clang 和 GCC 编译的。但是在标准中我还没有找到任何相关信息(或者我可能只是不能正确使用 ctrl+f ...)。而且我还没有发现有人像这样使用 requires-expression...
requires {...}
是一个 requires-expression 并且根据 expr.prim.req/p2 它是一个纯右值:
A requires-expression is a prvalue of type bool whose value is described below. Expressions appearing within a requirement-body are unevaluated operands.
所以是的,您可以在 constexpr bool
上下文中使用它。