如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
How to implement the generalized form of std::same_as (i.e. for more than two type parameters) that is agnostic to parameter order?
背景
我们知道概念std::same_as
是不可知序的(换句话说,对称的(:std::same_as<T, U>
等价于std::same_as<U, T>
(相关问题(。在这个问题中,我想实现一些更通用的东西:template <typename ... Types> concept same_are = ...
,它检查包Types
中的类型是否彼此相等。
我的尝试
#include <type_traits>
#include <iostream>
#include <concepts>
template <typename T, typename... Others>
concept same_with_others = (... && std::same_as<T, Others>);
template <typename... Types>
concept are_same = (... && same_with_others<Types, Types...>);
template< class T, class U> requires are_same<T, U>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
// Note the order <U, T> is intentional
template< class T, class U> requires (are_same<U, T> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
(我的意图是列举包中每一对可能的有序类型(
不幸的是,此代码无法编译,编译器抱怨对foo(int, int)
的调用不明确。我认为它认为are_same<U, T>
和are_same<T, U>
是不等价的。我想知道为什么代码失败,我该如何修复它(以便编译器将它们视为等效代码(?
这个概念的问题是:
template <typename T, typename... Others>
concept are_same = (... && std::same_as<T, Others>);
这个概念的标准化形式…正是这样。我们不能"展开"这一点(没有什么可做的(,目前的规则也不能通过概念的"部分"来规范化。
换句话说,你需要的是让你的概念正常化为:
... && (same-as-impl<T, U> && same-as-impl<U, T>)
进入:
... && (is_same_v<T, U> && is_same_v<U, T>)
并考虑一个折叠表达式&&
约束包含另一个折叠表达约束&&
,如果它的底层约束包含了另一个的底层约束。如果我们有这个规则,你的例子就会奏效。
将来可能会添加这一点,但对包容规则的担忧是,我们不想要求编译器全力以赴,实现一个完整的SAT求解器来检查约束包容。这个似乎并没有让它变得那么复杂(我们实际上只是通过折叠表达式添加&&
和||
规则(,但我真的不知道。
然而,请注意,即使我们有这种折叠表达式包含,are_same<T, U>
仍然不会包含std::same_as<T, U>
。它只包含are_same<U, T>
。我甚至不确定这是否可能。
来自cppreference.com Constraint_normalization
任何其他表达式E的范式都是原子约束,其表达式为E,其参数映射为单位映射。这包括所有的折叠表达式,甚至那些折叠在&;或||运算符。
所以
template <typename... Types>
concept are_same = (... && same_with_others<Types, Types...>);
是"原子"。
因此CCD_ 16和CCD_。
我不知道如何实现它:-(
churill是对的。使用std::concurrent_v可能会有所帮助。
template <typename T,typename... Types>
concept are_same = std::conjunction_v<std::same_as<T,Types>...>;
- 测试两个类型列表中的所有组合
- 检查两个模板参数是否相同
- sscanf() 有两个字符串参数
- 专门处理一个参数(C++模板)的两个模板参数
- 有没有办法仅在两个模板参数相同时才覆盖匹配的模板方法?
- 标准::原子::compare_exchange与两个memory_order参数一起使用的真实示例
- 如何共享特定于两个类的逻辑?
- std::具有两个输入参数的矢量构造函数
- 为什么 std::equal 模板由两个类参数化?
- 为什么我的类只适用于两个构造函数 C++
- 如何执行两个函数参数具有相同的模板类型
- 是否可以找到两个模板参数之间表达式的类型
- 如何将比较运算符应用于两个匿名结构中的每个变量
- 在不使用递归的情况下将 FFT 应用于两个非常大的数字的乘法
- 如何根据模板两个整数参数之间的关系对模板进行部分专用化
- 如何在一个构造函数中使用两个可变参数模板参数来绑定两个函数
- 当共享_ptr仅占用一个时,unique_ptr为什么要采用两个模板参数
- 带有两个类型参数的模板化函数在与错误检查宏一起使用时无法编译
- 当函数依赖于两个不同的类时,避免进行类型检查
- 两种模板类型和两个模板参数列表有什么区别