i'd write c++11 class mimics behavior of mathematical function. class takes input sets upon function defined, , possible set , value associated specific point in domain.
since number of sets comprise function domain not know priori, i'd use c++11 variadic templates define class follows:
template<typename first_set_type, typename... additional_sets_type> class function; so new function can created follows:
function<int, std::string, double> three_dim_function(s1, s2, s3); where s1, s2 , s3 std::set<int>, std::set<std::string> , std::set<double>, respectively. setting , getting value should resemble happens std::tuple:
three_dim_function.set<1, "a", 1.23>(12); double twelve = three_dim_function.get<1, "a", 1.23>(); most probably, std::unordered_map ideal data member store binding between domain , codomain:
std::unordered_map<std::tuple<first_set_type, additional_set_types...>, double> data_; i tried adapt code initialzing , accessing members of variadic class template, though 2 problems not identical (in case may not need store each single std::set).
edit #1: i'll try better stress issue i'm facing. in linked question, class created means of recursive calls. however, in case i'm having troubles in understanding how implement constructor, i.e., how set domain of function starting input sets. 1 possible way use constructor pre-fill keys generated cartesian product of input sets data_ data member. problem don't know how iterate on parameter pack.
tentative solution #1
here's tentative implementation: pastebin.com/fmrzc4dz based on contribution of @robert-mason. unfortunately, not compile (clang 4.1, osx 10.8.4) is_in_domain() called. however, @ first sight seems fine. wrong?
i'm leaving original answer below, i'll try address question variadic templates.
with variadic function template, not iterate on parameter pack. must instead use recursive function.
what use like:
template <class firstdomain, class ...domains> class function { public: typedef std::tuple<firstdomain, domains...> domain_t; static constexpr size_t dimension = sizeof...(domains) + 1; //+1 firstdomain private: std::tuple<std::set<firstdomain>, std::set<domains>...> domain; std::unordered_map<domain_t, double> map; template <size_t index = 0> typename std::enable_if<(index < dimension), bool>::type is_in_domain(const domain_t& t) const { const auto& set = std::get<index>(domain); if (set.find(std::get<index>(t)) != set.end()) { return is_in_domain<index + 1>(t); } return false; } template <size_t index = 0> typename std::enable_if<!(index < dimension), bool>::type is_in_domain(const domain_t& t) const { return true; } public: function(std::set<firstdomain> f, std::set<domains>... ds) : : domain(f, ds...) {} }; the trick combination of recursion , sfinae. need std::enable_if<> prevent compiler expanding calls std::get<>(), index checking done statically , cause compile error if never executed.
possible areas of improvement making construction more efficient moving sets if can. require perfect forwarding , other template magic, since you'd have let template argument deduction deduce types reference collapsing kicks in , use static_assert() error when deduced type not expected type (i.e. !(std::is_same<t, std::remove_cv<std::remove_reference<firstdomain>::type>::type>::value), in variadic form) , forwarding set std::forward().
(original answer)
in case, don't want use parameters template arguments. there sorts of rules concerning template arguments don't want have deal - of arguments have integral constant expressions.
you want use "normal" arguments, can pass them in std::unordered_map, can of type, , can runtime-defined:
i recommend like:
three_dim_function.set(1, "a", 1.23, 12); double twelve = three_dim_function.get(1, "a", 1.23); you can syntactic sugar if make nicer:
template <class first_type, class ...addl_types> class function { public: //... //left exercise reader void set(std::tuple<first_type, addl_types...>, double); class set_proxy { friend class function<first_type, addl_types...>; std::tuple<first_type, addl_types...> input; function<first_type, addl_types...>& parent; set_proxy(std::tuple<first_type, addl_types...> t, function<first_type, addl_types...>& f) : input(t), parent(f) {} set_proxy(const set_proxy&) = delete; set_proxy& operator=(const set_proxy&) = delete; public: //yes, know isn't right return type, i'm not sure what's idiomatic void operator=(double d) { parent.set(input, d); } }; set_proxy set(first_type f, addl_types... addl) { return set_proxy{std::make_tuple(f, addl...), *this}; } }; which lets do:
function<int, std::string, double> three_dim_function; three_dim_function.set(1, "a", 1.23) = 12;
Comments
Post a Comment