对于一个简单的编译时错误,如果可变参数包中的 any 类型重复,这很简单:
template <typename T> struct Base{};
template <typename... Ts> struct NoDuplicates : Base<Ts>... {
constexpr operator bool() const { return true; }
};
就是这样,如果您需要它,它的编译速度将比任何递归模板元编程、折叠表达式或类型特征方法更快。事实上,我知道在编译时没有更快的技术。
这是因为一个类不允许从同一个基类继承两次。它继承自 Base<T> 而不仅仅是 T 的原因是,如果 T 是您无法继承的类型,例如原始整数值、数组或 void 等。
使用方法:
template <typename... Ts>
class Foo {
static_assert(NoDuplicates<Ts...>{});
};
Foo<int, char, int> foo; // ERROR (see below)
<source>:3:34: error: duplicate base type 'Base<int>' invalid
3 | template <typename... Ts> struct NoDuplicates : Base<Ts>... {
现在,如果您不想要编译错误,但想要计算一个布尔值来指示是否有任何重复,这会稍微复杂一些,但也不算太糟糕。评论显示要检查的 3 个案例:
template <typename T, typename... Rest>
constexpr bool hasDuplicates() {
// Check T against each item in Rest, and if any match we have duplicates
if ((std::is_same_v<T, Rest> || ...))
return true;
// Is there anything left to check in Rest? If not, no duplicates.
if constexpr (sizeof...(Rest) == 0)
return false;
// T isn't duplicated, but is anything in Rest duplicated?
return hasDuplicates<Rest...>();
}
同样可以使用:
template <typename... Ts>
class Foo {
static_assert(not hasDuplicates<Ts...>());
};
Foo<int, std::string, std::string> foo; // Error, there are dupes
最后,如果您只关心特定类型是否重复,那就更容易了:
// Check if Needle is found 2 or more times in this Haystack
template <typename Needle, typename... Haystack>
constexpr bool hasDuplicateInList() {
return ((std::is_same_v<Needle, Haystack> + ...)) > 1;
}
就“抛出”而言,如果这是您想要的,如果您检测到布尔值在普通 if 中具有不允许的值,您总是可以抛出异常