使用 C++20 在编译时检查容器中是否存在重复元素
Check if there's duplicate element in an container in compile time with C++20
在 C++20 之前执行此操作的一种简单方法是执行嵌套循环:
template<typename Container>
constexpr bool has_duplicate(Container&& container)
{
for (auto it1 = container.cbegin(); it1 != container.cend(); ++it1)
for(auto it2 = container.cbegin(); it2 != it1; ++it2)
if (*it1 == *it2)
return 1;
return 0;
}
在range-based for loop中加入init-statement,并引入ranges::subrange
,我相信这个函数可以用range-based for loop重写:
template<std::ranges::input_range Container>
constexpr bool has_duplicate(Container&& container)
{
for(auto it = container.cbegin(); const auto& obj1 : container)
for(const auto& obj2 : std::ranges::subrange(container.cbegin(), it++))
if(obj1 == obj2)
return 1;
return 0;
}
虽然它在 gcc 上运行良好,但它无法用 clang 编译,除非我用 libc++ 手动设置它:https://godbolt.org/z/KM4a9zazs,并出现以下错误:
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/iterator_concepts.h:982:13: error: no matching function for call to '__begin'
= decltype(ranges::__cust_access::__begin(std::declval<_Tp&>()));
- 是我做错了什么,还是咔哒一声?
我也试过:
template<std::ranges::input_range Container>
constexpr bool has_duplicate(Container&& container)
{
for(auto index = 0ull; const auto& obj1 : container)
for(const auto& obj2 : container | std::ranges::views::take(index++))
if(obj1 == obj2) return 1;
return 0;
}
gcc 再次没有问题,但 clang 对任何一个库都失败了。
Godbolt 默认使用 libstdc++
,即使使用 Clang 编译时也是如此,这有点令人困惑。
Clang 是否应该完全支持链接到 libstdc++
,我不能说,但是例如以下 Clang 错误报告强调了相同的问题:
错误报告中的最小示例:
#include <ranges>
void foo() {
std::ranges::iota_view iota(2, 10);
iota.begin();
}
error: no matching function for call to '__begin
'
在 C++20 之前执行此操作的一种简单方法是执行嵌套循环:
template<typename Container>
constexpr bool has_duplicate(Container&& container)
{
for (auto it1 = container.cbegin(); it1 != container.cend(); ++it1)
for(auto it2 = container.cbegin(); it2 != it1; ++it2)
if (*it1 == *it2)
return 1;
return 0;
}
在range-based for loop中加入init-statement,并引入ranges::subrange
,我相信这个函数可以用range-based for loop重写:
template<std::ranges::input_range Container>
constexpr bool has_duplicate(Container&& container)
{
for(auto it = container.cbegin(); const auto& obj1 : container)
for(const auto& obj2 : std::ranges::subrange(container.cbegin(), it++))
if(obj1 == obj2)
return 1;
return 0;
}
虽然它在 gcc 上运行良好,但它无法用 clang 编译,除非我用 libc++ 手动设置它:https://godbolt.org/z/KM4a9zazs,并出现以下错误:
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/iterator_concepts.h:982:13: error: no matching function for call to '__begin'
= decltype(ranges::__cust_access::__begin(std::declval<_Tp&>()));
- 是我做错了什么,还是咔哒一声?
我也试过:
template<std::ranges::input_range Container>
constexpr bool has_duplicate(Container&& container)
{
for(auto index = 0ull; const auto& obj1 : container)
for(const auto& obj2 : container | std::ranges::views::take(index++))
if(obj1 == obj2) return 1;
return 0;
}
gcc 再次没有问题,但 clang 对任何一个库都失败了。
Godbolt 默认使用 libstdc++
,即使使用 Clang 编译时也是如此,这有点令人困惑。
Clang 是否应该完全支持链接到 libstdc++
,我不能说,但是例如以下 Clang 错误报告强调了相同的问题:
错误报告中的最小示例:
#include <ranges> void foo() { std::ranges::iota_view iota(2, 10); iota.begin(); }
error: no matching function for call to '
__begin
'