// Created by Sergey on 12.09.14.
// Copyright (c) 2014 Sergey. All rights reserved.
//
#include <iostream>
#include <chrono>
#include <map>
#include <string>
template <class T, class ValueType>
class StrongType
{
public:
inline explicit operator ValueType() const { return _value;}
inline bool operator == (const StrongType &other) const
{
return _value == other._value;
}
inline bool operator != (const StrongType &other) const
{
return _value != other._value;
}
inline bool operator < (const StrongType &other) const
{
return _value < other._value;;
}
inline bool operator > (const StrongType &other) const
{
return _value > other._value;
}
inline bool operator <= (const StrongType &other) const
{
return _value <= other._value;
}
inline bool operator >= (const StrongType &other) const
{
return _value >= other._value;
}
protected:
explicit StrongType(ValueType value):_value(value) {}
private:
ValueType _value;
};
template <class T, class ValueType = int>
class StringCache
{
public:
static_assert(std::is_integral<ValueType>::value, "not integral type");
class Type: public StrongType<T,ValueType>
{
friend class StringCache;
private:
explicit Type(ValueType value):StrongType<T,ValueType>(value){}
};
static Type get(const std::string &value)
{
return Type(_values.insert(std::make_pair(value, _values.size() + 1)).first->second);
}
static Type find(const std::string &value)
{
std::map<std::string,int>::const_iterator it =_values.find(value);
if(it == _values.end())
return Type(0);
else
return Type(it->second);
}
static const std::string& to_string(const Type &type)
{
static const std::string empty;
if(static_cast<ValueType>(type)>=_values.size())
return empty;
for(const auto &it:_values)
if(it.second == static_cast<ValueType>(type))
return it.first;
return empty;
}
private:
static std::map<std::string,int> _values;
};
template <class T, class ValueType>
std::map<std::string,int> StringCache<T,ValueType>::_values;
class ArmorType:public StringCache<ArmorType>{};
class WeaponType:public StringCache<WeaponType>{};
typedef int ArmorDescription;
std::string armorId0("armor0");
std::string armorId1("armor1");
std::string armorId2("armor2");
std::string armorId3("armor3");
std::string armorId4("armor4");
std::string armorId5("armor5");
std::string armorId6("armor6");
std::string armorId7("armor7");
std::string armorId8("armor8");
std::string armorId9("armor9");
int test1(const std::map<ArmorType::Type,ArmorDescription> &armor)
{
static const ArmorType::Type value(ArmorType::get(armorId1));
return armor.find(value)->second;
}
int test2(const std::map<std::string,ArmorDescription> &armor)
{
static const std::string value(armorId1);
return armor.find(value)->second;
}
int main(int argc, const char * argv[])
{
std::map<ArmorType::Type,ArmorDescription> armorHash;
std::map<std::string,ArmorDescription> armorString;
armorHash.insert(std::make_pair(ArmorType::get(armorId0), ArmorDescription(0)));
armorHash.insert(std::make_pair(ArmorType::get(armorId1), ArmorDescription(1)));
armorHash.insert(std::make_pair(ArmorType::get(armorId2), ArmorDescription(2)));
armorHash.insert(std::make_pair(ArmorType::get(armorId3), ArmorDescription(3)));
armorHash.insert(std::make_pair(ArmorType::get(armorId4), ArmorDescription(4)));
armorHash.insert(std::make_pair(ArmorType::get(armorId5), ArmorDescription(5)));
armorHash.insert(std::make_pair(ArmorType::get(armorId6), ArmorDescription(6)));
armorHash.insert(std::make_pair(ArmorType::get(armorId7), ArmorDescription(7)));
armorHash.insert(std::make_pair(ArmorType::get(armorId8), ArmorDescription(8)));
armorHash.insert(std::make_pair(ArmorType::get(armorId9), ArmorDescription(9)));
armorString.insert(std::make_pair(armorId0, ArmorDescription(0)));
armorString.insert(std::make_pair(armorId1, ArmorDescription(1)));
armorString.insert(std::make_pair(armorId2, ArmorDescription(2)));
armorString.insert(std::make_pair(armorId3, ArmorDescription(3)));
armorString.insert(std::make_pair(armorId4, ArmorDescription(4)));
armorString.insert(std::make_pair(armorId5, ArmorDescription(5)));
armorString.insert(std::make_pair(armorId6, ArmorDescription(6)));
armorString.insert(std::make_pair(armorId7, ArmorDescription(7)));
armorString.insert(std::make_pair(armorId8, ArmorDescription(8)));
armorString.insert(std::make_pair(armorId9, ArmorDescription(9)));
auto armor1It = armorHash.find(ArmorType::find(armorId1));
auto armor2It = armorHash.find(ArmorType::find(armorId2));
auto armor10It = armorHash.find(ArmorType::find("armor10"));
std::cout << ArmorType::to_string(armor1It->first) << ":" << static_cast<int>(armor1It->first) << std::endl;
std::cout << ArmorType::to_string(armor2It->first) << ":" << static_cast<int>(armor2It->first) << std::endl;
std::cout << ArmorType::to_string(armor10It->first) << ":" << static_cast<int>(armor10It->first) << std::endl;
int ret1 = 0;
int ret2 = 0;
std::chrono::high_resolution_clock::time_point t = std::chrono::high_resolution_clock::now();
for(int i=0;i<1000000;++i)
ret1 += test1(armorHash);
auto duration = std::chrono::high_resolution_clock::now() - t;
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() << std::endl;
t = std::chrono::high_resolution_clock::now();
for(int i=0;i<1000000;++i)
ret2 += test2(armorString);
duration = std::chrono::high_resolution_clock::now() - t;
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() << std::endl;
return 0;
}