【发布时间】:2021-11-13 02:27:15
【问题描述】:
有一个很好的问题 (Which substitution failures are not allowed in requires clauses?) 提出了下一个问题。
需要编写一个编译时函数template<typename... Ts> constexpr bool allTypesUnique(),如果所有参数类型都是唯一的,它将返回true,否则返回false。并且限制是不成对比较参数类型。不幸的是,答案只解释了为什么不能用某种特定的方法来实现这样的功能。
我认为解决方案可以使用多重继承来实现。这个想法是让一个类继承自多个类:Ts 中的每个类型 T 一个。每个这样的类都定义了一个虚拟函数,其签名取决于T。如果在Ts 中多次发现某些T,则子类中的函数f 将覆盖基类中的函数并且可以检测到:
template<typename> struct A{};
template<typename T, typename... Ts>
struct B : B<Ts...> {
using B<Ts...>::f;
constexpr virtual void f(A<T>, bool & unique) { if( ++count > 1 ) unique = false; }
int count = 0;
};
template<typename T>
struct B<T> {
constexpr virtual void f(A<T>, bool & unique) { if( ++count > 1 ) unique = false; }
int count = 0;
};
template<typename... Ts>
constexpr bool allTypesUnique() {
B<Ts...> b;
bool res = true;
( b.f( A<Ts>{}, res ), ... );
return res;
}
int main() {
static_assert( allTypesUnique<void>() );
static_assert( allTypesUnique<void, int&>() );
static_assert( !allTypesUnique<int&, int&>() );
static_assert( allTypesUnique<char, short, int>() );
static_assert( !allTypesUnique<char, short, char>() );
}
演示:https://gcc.godbolt.org/z/8jhnE7P11
只是好奇,解决方案是否正确,是否有更简单的解决方案来解决这个问题?
【问题讨论】:
-
我添加了 C++20 标签,因为在此之前,
virtual函数不能是constexpr。 -
在给定引用类型时会中断,但应该很容易修复。
-
为什么不能成对比较参数类型的限制?这似乎很随意。这纯粹是学术活动吗?
-
为什么避免成对比较很重要/有用?请注意,您没有写“避免所有对比较”,您需要完全避免此类比较。这会阻止使用基于
std::is_same_v的方法。 -
感谢您的 cmets。我做了一个小的代码更改以支持引用类型。
标签: c++ overloading variadic-templates multiple-inheritance c++20