【发布时间】:2021-01-30 20:24:55
【问题描述】:
想知道对于parameters pack 上的concepts,什么语法最有效/最方便,包括当类型(ou 值的类型)相互依赖时的values template-parameters?
例如,使用以下函数:
equal_v<values...>在所有值相等时为真
template <auto... values>
constexpr static auto equal_v = []() consteval
{
static_assert(sizeof...(values) > 0, "equal_v : no arguments");
constexpr auto first_value = std::get<0>(std::tuple{values...});
static_assert(
(std::equality_comparable_with<decltype(values), decltype(first_value)> && ...),
"equal_v : cannot compare values");
return ((values == first_value) && ...);
}
();
我会的:
template <typename ... Ts>
concept are_equality_comparable = requires(Ts ... values)
{
{
std::conditional_t<(std::equality_comparable_with<decltype(std::get<0>(std::tuple{values...})), decltype(values)> && ...), std::true_type, std::false_type>{}
} -> std::same_as<std::true_type>;
};
template <auto ... values>
requires(are_equality_comparable<decltype(values)...>)
constexpr static auto equal_v = []() consteval {
static_assert(sizeof...(values) > 0, "equal_v : no arguments");
constexpr auto first_value = std::get<0>(std::tuple{values...});
return ((values == first_value) && ...);
}();
这有点难看,使用std::conditional<..., std::true_type, std::false_type> 作为std::same_as<..., std::true_type> 参数。
所以我最终得到了以下语法,我认为这是最优雅的:
template <auto first_value, auto ... values>
requires (std::equality_comparable_with<decltype(first_value), decltype(values)> && ...)
constexpr static auto equal_v = []() consteval {
return ((values == first_value) && ...);
}();
或者,第一个参数不是强制性的:
template <auto ... values>
requires (std::equality_comparable_with<decltype(std::get<0>(std::tuple{values...})), decltype(values)> && ...)
constexpr static auto equal_v = []() consteval {
return ((values == std::get<0>(std::tuple{values...})) && ...);
}();
但是,由于所有值都取决于第一个值,
我还没有想出使用这种假设语法的方法:
template <auto first_value, std::equality_comparable_with<decltype(first_value)> ... values>
constexpr static auto equal_v = []() consteval {
return ((values == first_value) && ...);
}();
所以,这里有几点:
- 是否有一种优雅的方式来使用概念来限制模板值的类型而不是模板类型参数?
- 有没有办法限制模板参数包中相互依赖的类型而不修改函数签名,没有
requires子句? 例如template <auto ... values>而不是template <auto first_value, auto ... values>
[编辑]
正如 cmets 中的 artyer 所指出的,concept auto value 是一种有效的语法。
此外,这不适用于 MSVC 19.28,因为它会导致:
错误 C7601:不满足关联的约束
也不是 GCC 10.2:
错误:不满足占位符约束
但适用于 Clang 11.0.1。
template <auto first_value, std::equality_comparable_with<decltype(first_value)> auto ... values> constexpr static auto equal_v = []() consteval {
return ((values == first_value) && ...);
}();
[EDIT_2]
为了使equal_v<>为真:
template <auto first_value = int{}, std::equality_comparable_with<decltype(first_value)> auto ... values>
constexpr static auto equal_v = []() consteval {
return ((values == first_value) && ...);
}();
【问题讨论】:
-
对于你要找的最后一个
template<auto first_value, std::equalityy_comparable_with<decltype(first_value)> auto... values>(完全一样,如果你想限制一个函数参数,你有concept auto name) -
太棒了!非常感谢。如果我是对的,en.cppreference.com/w/cpp/language/constraints 上没有提到这种语法
-
这工作正常,但如前所述,它使用 2 个模板参数而不是 1 个
cpp template <auto first_value, std::equality_comparable_with<decltype(first_value)> auto ... values> constexpr static auto equal_v = []() consteval { return ((values == first_value) && ...); }(); -
顺便说一句,
equal_v<>不是微不足道的true,而是一个错误,这是非常出乎意料的。 -
@Guss:它是P1141,尽管在 P0734 之前的原始提案版本中删除了一些模糊相似的语法。
标签: c++ c++20 c++-concepts