如何在表达式编译错误时将概念评估为假
how to evaluate concept to false upon expression compilation error
我试图更改以下示例概念代码,该代码在某些输入下导致错误而不是评估 false:
template <typename T>
constexpr bool inner = T::prop;
template <typename T>
concept outer = inner<T>;
struct pass {static constexpr bool prop = true;};
struct fail {static constexpr bool prop = false;};
struct bad_fail {static constexpr std::tuple<> prop{};};
static_assert(outer<pass>);
static_assert(not outer<fail>);
static_assert(not outer<bad_fail>);
这有编译错误 cannot convert 'const std::tuple<>' to 'const bool'
。
我试图只评估 inner
当它使用 requires
子句编译时:
template <typename T>
constexpr bool inner = T::prop;
template <typename T>
concept outer = []() consteval -> bool {
if constexpr (
requires() {{
inner<T>
} -> std::same_as<const bool&>;}
) {
return inner<T>;
} else {
return false;
}
}();
struct pass {static constexpr bool prop = true;};
struct fail {static constexpr bool prop = false;};
struct bad_fail {static constexpr std::tuple<> prop{};};
static_assert(outer<pass>);
static_assert(not outer<fail>);
static_assert(not outer<bad_fail>);
这会导致一个令人困惑的错误:
error: non-constant condition for static assertion ... static_assert(not outer<bad_fail>)
同样的 cannot convert 'const std::tuple<>' to 'const bool'
似乎来自第二个 inner
。 (编译器不指定)
然后我尝试将编译检查和真实性检查合并到 requires
子句中的 static_assert
检查中:
template <typename T>
constexpr bool inner = T::prop;
template <typename T>
concept outer = requires() {{
[]() constexpr {
static_assert(inner<T>);
}()
} -> std::same_as<void>;};
struct pass {static constexpr bool prop = true;};
struct fail {static constexpr bool prop = false;};
struct bad_fail {static constexpr std::tuple<> prop{};};
static_assert(outer<pass>);
static_assert(not outer<fail>);
//static_assert(not outer<bad_fail>);
这会导致一个令人困惑的错误:
error: static assertion failed ... static_assert(not outer<fail>)
这令人困惑,因为:
error: static assertion failed ... static_assert(inner<T>)
也被抛出,暗示 static_assert
转义 requires
子句。果然是真的:
template <std::monostate>
concept should_false = requires() {{
[]() constexpr {
static_assert(false);
}()
} -> std::same_as<void>;};
因为这有编译错误error: static assertion failed ... static_assert(false)
!
如何让 outer<bad_fail>
计算为 false 而没有编译错误?
可以使用requires
子句初始化inner
,首先要求T::prop
的return类型必须是const bool&
,然后使用嵌套 requires
,其值 T::prop
#include <concepts>
template <typename T>
constexpr bool inner = requires {
{T::prop} -> std::same_as<const bool&>;
requires T::prop;
};
template <typename T>
concept outer = inner<T>;
我试图更改以下示例概念代码,该代码在某些输入下导致错误而不是评估 false:
template <typename T>
constexpr bool inner = T::prop;
template <typename T>
concept outer = inner<T>;
struct pass {static constexpr bool prop = true;};
struct fail {static constexpr bool prop = false;};
struct bad_fail {static constexpr std::tuple<> prop{};};
static_assert(outer<pass>);
static_assert(not outer<fail>);
static_assert(not outer<bad_fail>);
这有编译错误 cannot convert 'const std::tuple<>' to 'const bool'
。
我试图只评估 inner
当它使用 requires
子句编译时:
template <typename T>
constexpr bool inner = T::prop;
template <typename T>
concept outer = []() consteval -> bool {
if constexpr (
requires() {{
inner<T>
} -> std::same_as<const bool&>;}
) {
return inner<T>;
} else {
return false;
}
}();
struct pass {static constexpr bool prop = true;};
struct fail {static constexpr bool prop = false;};
struct bad_fail {static constexpr std::tuple<> prop{};};
static_assert(outer<pass>);
static_assert(not outer<fail>);
static_assert(not outer<bad_fail>);
这会导致一个令人困惑的错误:
error: non-constant condition for static assertion ... static_assert(not outer<bad_fail>)
同样的 cannot convert 'const std::tuple<>' to 'const bool'
似乎来自第二个 inner
。 (编译器不指定)
然后我尝试将编译检查和真实性检查合并到 requires
子句中的 static_assert
检查中:
template <typename T>
constexpr bool inner = T::prop;
template <typename T>
concept outer = requires() {{
[]() constexpr {
static_assert(inner<T>);
}()
} -> std::same_as<void>;};
struct pass {static constexpr bool prop = true;};
struct fail {static constexpr bool prop = false;};
struct bad_fail {static constexpr std::tuple<> prop{};};
static_assert(outer<pass>);
static_assert(not outer<fail>);
//static_assert(not outer<bad_fail>);
这会导致一个令人困惑的错误:
error: static assertion failed ... static_assert(not outer<fail>)
这令人困惑,因为:
error: static assertion failed ... static_assert(inner<T>)
也被抛出,暗示 static_assert
转义 requires
子句。果然是真的:
template <std::monostate>
concept should_false = requires() {{
[]() constexpr {
static_assert(false);
}()
} -> std::same_as<void>;};
因为这有编译错误error: static assertion failed ... static_assert(false)
!
如何让 outer<bad_fail>
计算为 false 而没有编译错误?
可以使用requires
子句初始化inner
,首先要求T::prop
的return类型必须是const bool&
,然后使用嵌套 requires
,其值 T::prop
#include <concepts>
template <typename T>
constexpr bool inner = requires {
{T::prop} -> std::same_as<const bool&>;
requires T::prop;
};
template <typename T>
concept outer = inner<T>;