我有参数类,它包含不同类型的参数。
std::map<std::string, std::string > _params_string;
std::map<std::string, int > _params_int;
std::map<std::string, double > _params_double;
std::map<std::string, bool > _params_bool;
我想有一个方法,用户可以将参数设置为:
template<class type>
inline void set(const std::string &key, const type &value)
{
_params[key] = value;
}
但是,由于我对不同类型的参数有不同的存储空间,因此它变得一团糟。
对于不同类型的参数,是否有人对共同接口/存储有任何建议?
答案 0 :(得分:1)
您可以使用像Boost.Variant这样的歧视联盟将所有地图缩小为:
using Parameter = boost::variant<int, double, bool, std::string>;
std::map<std::string, Parameter> _params;
现在你只有一张地图,你(显然)只需要一个set()
:
template <class T>
void set(std::string const& key, T const& value) {
_params[key] = value;
}
每个参数都会知道它所持有的类型。这另外解决了在多个地图中存在相同密钥的问题 - 因为这没有多大意义。
答案 1 :(得分:0)
我可以看到几种方法来做到这一点。但是我能想到的最简单的一个需要C ++ 14的支持。
template <typename T>
using stringmap = std::map<std::string, T>;
std::tuple<stringmap<std::string>, stringmap<std::int>, stringmap<std::double>, stringmap<std::bool>> _params;
template <typename T>
explicit void set(const std::string & key, const T & value) {
std::get<stringmap<T>>(_params)[key] = value;
}
您可以使用get
进行类似的舞蹈,并且您始终可以使用std::get<stringmap<T>>(_params)
为特定类型引用所选地图。
只要您愿意在可以按类型索引的元组上编写get例程,就可以以相同的方式执行此操作。这是我写的一个叫tget
。
template <std::size_t Pos, std::size_t Count, typename T, typename... Rest>
struct _tget_tuple_helper {
static constexpr auto pos = Pos;
static constexpr auto count = Count;
};
template <std::size_t Pos, std::size_t Count, typename T, typename S, typename... Rest>
struct _tget_tuple_helper<Pos, Count, T, S, Rest...> {
static constexpr auto match = std::is_same<T, typename std::decay<S>::type>::value;
using parent = _tget_tuple_helper<Pos + 1, match ? Count + 1 : Count, T, Rest...>;
static constexpr auto pos = match ? Pos : parent::pos;
static constexpr auto count = parent::count;
};
template <typename T, typename... Types>
using tget_tuple_helper = _tget_tuple_helper<0, 0, typename std::decay<T>::type, Types...>;
template <typename T, typename... Types>
constexpr
typename std::enable_if<tget_tuple_helper<T, Types...>::count == 1, T &>::type
tget(std::tuple<Types...> & t) {
return std::get<tget_tuple_helper<T, Types...>::pos>(t);
}
template <typename T, typename... Types>
constexpr
typename std::enable_if<tget_tuple_helper<T, Types...>::count == 1, const T &>::type
tget(const std::tuple<Types...> & t) {
return std::get<tget_tuple_helper<T, Types...>::pos>(t);
}
使用此功能,您可以在C ++ 14示例中将std::get
替换为tget
。其他一切都应该是一样的。
答案 2 :(得分:0)
您可以尝试使用任何类型的此类std::map<std::string,std::experimental::any>