有一个很好的问题(require 子句中不允许哪些替换失败? https://stackoverflow.com/questions/59555623/which-substitution-failures-are-not-allowed-in-requires-clauses)提出下一个问题。
需要编写一个编译时函数template<typename... Ts> constexpr bool allTypesUnique()
将会返回true
如果所有参数类型都是唯一的,并且false
否则。并且限制是不要成对比较参数类型。不幸的是,答案仅解释了为什么无法使用某些特定方法来实现此类功能。
我认为可以使用多重继承来实现解决方案。这个想法是让一个类继承多个类:每种类型一个类T
in Ts
。每个这样的类都定义了一个虚函数,其签名取决于T
。如果有一些T
被发现不止一次Ts
然后函数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>() );
}
Demo: https://gcc.godbolt.org/z/8jhnE7P11 https://gcc.godbolt.org/z/8jhnE7P11
只是好奇,这个解决方案是否正确,是否有更简单的解决方案来解决这个问题?