c++ 20中可迭代容器的概念是什么?



我还在用c++ 17。我试图编写一个通用代码,以检索"顶级计数"。元素从任何可迭代容器。但在我看来,这看起来有些笨拙。

是否有更好的方法来检查c++ 20中带有概念的类型特征?那会是什么样子?

需求可以从cppreference中显示的基于for的范围中提取,并且将是:

auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}

so,begin,end,++,*,!=


我通过使用SFINAE机制定义类型特征构建了一个解决方案。请参阅:

#include <iostream>
#include <utility>
#include <unordered_map>
#include <queue>
#include <vector>
#include <iterator>
#include <type_traits>
#include <string>

// Helper for type trait We want to identify an iterable container ----------------------------------------------------
template <typename Container>
auto isIterableHelper(int) -> decltype (
std::begin(std::declval<Container&>()) != std::end(std::declval<Container&>()),     // begin/end and operator !=
++std::declval<decltype(std::begin(std::declval<Container&>()))&>(),                // operator ++
void(*std::begin(std::declval<Container&>())),                                      // operator*
void(),                                                                             // Handle potential operator ,
std::true_type{});
template <typename T>
std::false_type isIterableHelper(...);
// The type trait -----------------------------------------------------------------------------------------------------
template <typename Container>
using is_iterable = decltype(isIterableHelper<Container>(0));
// Some Alias names for later easier reading --------------------------------------------------------------------------
template <typename Container>
using ValueType = std::decay_t<decltype(*std::begin(std::declval<Container&>()))>;
template <typename Container>
using Pair = std::pair<ValueType<Container>, size_t>;
template <typename Container>
using Counter = std::unordered_map<ValueType<Container>, size_t>;
template <typename Container>
using UnderlyingContainer = std::vector<Pair<Container>>;
// Predicate Functor
template <class Container> struct LessForSecondOfPair {
bool operator () (const Pair<Container>& p1, const Pair<Container>& p2) { return p1.second < p2.second; }
};
template <typename Container>
using MaxHeap = std::priority_queue<Pair<Container>, UnderlyingContainer<Container>, LessForSecondOfPair<Container>>;

// Function to get most frequent used number in any Container ---------------------------------------------------------
template <class Container>
auto topFrequent(const Container& data) {
if constexpr (is_iterable<Container>::value) {
// Count all occurences of data
Counter<Container> counter{};
for (const auto& d : data) counter[d]++;
// Build a Max-Heap
MaxHeap<Container> maxHeap(counter.begin(), counter.end());
// Return most frequent number
return maxHeap.top().first;
}
else
return data;
}
// Test
int main() {
std::vector testVector{ 1,2,2,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,6,7 };
std::cout << "Most frequent is: " << topFrequent(testVector) << "n";
double cStyleArray[] = { 1.1, 2.2, 2.2, 3.3, 3.3, 3.3 };
std::cout << "Most frequent is: " << topFrequent(cStyleArray) << "n";
std::string s{ "abbcccddddeeeeeffffffggggggg" };
std::cout << "Most frequent is: " << topFrequent(s) << "n";
double value = 12.34;
std::cout << "Most frequent is: " << topFrequent(value) << "n";
return 0;
}

那么,c++ 20的解决方案是什么呢?


使用Microsoft Visual Studio Community 2019, Version 16.8.2开发并测试。

在clang11.0和gcc10.2下编译和测试,标记为--std=c++17 -Wall -Wextra -Wpedantic

语言:C + + 17

你的ValueType性状基本上是std::ranges::range_value_t,你的is_iterable性状基本上是conceptstd::ranges::range:

template <typename Container>
using ValueType = std::ranges::range_value_t<Container>;
template <class Container>
auto topFrequent(const Container& data) {
if constexpr (std::ranges::range<Container>) {
// Count all occurences of data
Counter<Container> counter{};
for (const auto& d : data) counter[d]++;
// Build a Max-Heap
MaxHeap<Container> maxHeap(counter.begin(), counter.end());
// Return most frequent number
return maxHeap.top().first;
}
else
return data;
}

看演示。

最新更新