自动化测试
template < typename Contain >
//重载提取操作符<<
inline std::ostream&
operator<<( std::ostream& o, const std::optional< Contain >& object ){
using namespace std::literals::string_literals;
if( !object ) // optional< T >::operator bool()隐式转换
return ( o << "null"s ); //cache未命中
return ( o << object.value() ); //cache命中
}
//自动化测试
int main( void ){
FIFOCache< std::ptrdiff_t, int > cache;
//cache default capacity == 64
int counter { 32 };
//读写操作总次数
srand( ( unsigned)time( nullptr ) );
//随机数种子
while( counter-- ){
if( rand() % 101 <= 80 ){
//80% load写操作
int key { rand() % 64 };
int value { rand() % 64 };
std::printf("#put {key : %d, value: %d}...\n\n", key, value );
cache.put({key,value});
}else{
//20% 读操作
int key { rand() %64 };
std::printf("#try-get {key: %d, value : ?}...\n\n", key );
std::cout << "value:\t" << cache.get(key) << '\n';
}
}
return 0;
}
运行结果
FIFOCache实现
#include <unordered_map>
#include <list>
#include <concepts>
#include <functional>
#include <optional>
#include <iostream>
template < class Key, class Value >
requires requires{
std::hash< Key >{}( std::declval< Key >() );
}
class FIFOCache{
public:
static constexpr std::size_t DEFAULT { 64 };
private:
std::list< Key > cache;
mutable std::unordered_map< Key, Value > hash;
std::size_t capacity { DEFAULT };
public:
typedef Key key_type;
typedef Value value_type;
typedef std::pair< Key, Value > pair_type;
typedef std::optional< Value > return_type;
FIFOCache( void ) noexcept = default;
FIFOCache( const FIFOCache& ) noexcept = default;
FIFOCache( FIFOCache&& ) noexcept = default;
FIFOCache( std::size_t __capacity ) : capacity( __capacity ) { }
[[discard]] return_type get( const Key& key ) const {
if( !hash.count( key ) )
return static_cast< std::optional< Value > >( std::nullopt );
return return_type{ hash[key] };
}
void put( const pair_type& p ){
auto [key, value] = p;
if( hash.count(key)){
hash[key] = value;
return;
}
if(cache.size() == capacity){
hash.erase(cache.front());
cache.pop_front();
}
hash.insert(p);
cache.push_back(key);
}
};
template < typename Contain >
std::ostream& operator<<( std::ostream& o, const std::optional< Contain >& object ){
using namespace std::literals::string_literals;
if( !object ) return ( o << "null"s );
return ( o << object.value() );
}