Skip to content

Instantly share code, notes, and snippets.

@tell
Last active December 18, 2016 13:01
Show Gist options
  • Save tell/4bbcca7e69a9db1f37a6880099e821bd to your computer and use it in GitHub Desktop.
Save tell/4bbcca7e69a9db1f37a6880099e821bd to your computer and use it in GitHub Desktop.
Java Properties like map on C++
### https://raw.github.com/github/gitignore/afbff9027d02ccfc680e031f6c295f79ad61662d/C++.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
// vim: set expandtab :
#include <iostream>
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
#include "properties.hpp"
using namespace std;
int main(int argc, char *argv[]) {
if (argc < 2) { return 1; }
string x(argv[1]);
string key = "argv1";
cout << key << " is " << x << endl;
tell::Properties mc{{key, x}};
if (auto a = mc.get(key)) {
cout << "get() is " << *a << endl;
}
if (auto a = mc.getInt(key)) {
cout << "getInt() is " << *a << endl;
}
if (auto a = mc.getInt64(key)) {
cout << "getInt64() is " << *a << endl;
}
if (auto a = mc.getFloat(key)) {
cout << "getFloat() is " << *a << endl;
}
if (auto a = mc.getDouble(key)) {
cout << "getDouble() is " << *a << endl;
}
return 0;
}
CC = $(CXX)
CPPFLAGS += -std=c++11
CXXFLAGS += -Ofast
%.out: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
all: lc.out
lc.o: properties.hpp
// vim: set expandtab :
#pragma once
#include <unordered_map>
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
namespace tell {
template<class T>
using opt = boost::optional<T>;
constexpr auto none = boost::none;
using boost::lexical_cast;
using boost::conversion::try_lexical_convert;
namespace details {
template<class T>
opt<T> getGeneric(const std::string& repr) {
T result;
if (try_lexical_convert<T>(repr, result)) {
return result;
} else {
return none;
}
}
#if defined(DETAILS_GET_MEMBERS_BY_GET_GENERIC)
#error "DETAILS_GET_MEMBERS_BY_GET_GENERIC is already defined."
#endif
#define DETAILS_GET_MEMBERS_BY_GET_GENERIC(type, name) \
opt< type > name (const std::string& key) const { \
return details::getGeneric< type >(map_.at(key)); \
}
} // namespace details
class Properties {
std::unordered_map<std::string, std::string> map_;
public:
Properties() {};
Properties(std::initializer_list< std::initializer_list<std::string> > init) {
for (auto&& kv : init) {
if (kv.size() == 2) {
auto iter = kv.begin();
auto& k = *iter++;
auto& v = *iter;
map_[k] = v;
}
}
}
template<class T>
void set(const std::string& key, const T& value) {
map_[key] = lexical_cast<std::string>(value);
}
void set(const std::string& key, const std::string& value) {
map_[key] = value;
}
opt<std::string> get(const std::string& key) const {
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
} else {
return none;
}
}
#if 1
DETAILS_GET_MEMBERS_BY_GET_GENERIC(int, getInt)
DETAILS_GET_MEMBERS_BY_GET_GENERIC(int64_t, getInt64)
DETAILS_GET_MEMBERS_BY_GET_GENERIC(float, getFloat)
DETAILS_GET_MEMBERS_BY_GET_GENERIC(double, getDouble)
#undef DETAILS_GET_MEMBERS_BY_GET_GENERIC
#else
opt<int> getInt(const std::string& key) const {
return getGeneric<int>(map_.at(key));
}
opt<int64_t> getInt64(const std::string& key) const {
return getGeneric<int64_t>(map_.at(key));
}
opt<float> getFloat(const std::string& key) const {
return getGeneric<float>(map_.at(key));
}
opt<double> getDouble(const std::string& key) const {
return getGeneric<double>(map_.at(key));
}
#endif
};
} // namespace tell
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment