#include <iostream>
#include <utility>
#include <map>
#include <string>
#include <initializer_list>
#include <cstring>
#include <stdexcept>
namespace LiteralSwitch {
// simple hash function
constexpr unsigned int dbj2Hash(const char* str, size_t size, int index = 0)
{
return !str[index] ? 0x1505 : (dbj2Hash(str, size, index + 1) * 0x21) ^ str[index];
}
// Create a literal type for short-hand case strings
constexpr unsigned int operator"" _C ( const char str[], size_t size)
{
return dbj2Hash(str, size - 1);
}
struct CaseLabel
{
typedef const char* label_type;
typedef uint32_t value_type;
typedef std::pair<const label_type, value_type> store_type;
constexpr CaseLabel(const char* str)
: data_(std::make_pair(str, dbj2Hash(str, strlen(str))))
{
}
constexpr operator value_type() const { return data_.second; }
constexpr operator label_type() const { return data_.first; }
constexpr operator store_type() const { return data_; }
private:
const store_type data_;
};
struct compare {
bool operator()(const char *left, const char *right) const
{
return strcmp(left, right) < 0;
}
};
struct CaseLabelSet
: private std::map<CaseLabel::label_type, CaseLabel::value_type, compare>
{
CaseLabelSet(std::initializer_list<CaseLabel> values)
{
for(auto x : values) insert(x);
}
CaseLabel::value_type operator()(const std::string& label) const
{
return operator()(label.c_str());
}
CaseLabel::value_type operator()(const char* label) const
{
auto it = find(label);
if(it == end())
{
throw std::invalid_argument("Case label not found");
}
return it->second;
}
};
}
using namespace LiteralSwitch;
void Test(const std::string& cond)
{
static const CaseLabelSet setValues = {"Hello", "World"};
try
{
switch(setValues(cond))
{
case "Hello"_C: std::cout << "Goodbye"; break;
case "World"_C: std::cout << "Planet"; break;
default: std::cout << "BOGUS!";
}
std::cout << std::endl;
}
catch(std::invalid_argument)
{
std::cout << "exception on unknown switch/case value. should go to default" << std::endl;
}
}
int main()
{
Test("Hello");
Test("World");
Test("hello");
}