ノート 3/15
以前からやりたかったことは、json11に(key, var)の組のリストを与えて一括で変数varにアイテム名keyの値を代入することだった。これは前回のapply関数で実現できる。
次に、項目名keyの値を関数fで変換した後varに代入したくなった。
template <class T> void bind(T const& t) { if constexpr (util::is_tuple_v<T>) { util::apply(t, [this](auto& i) { i.var = i.functor(get<typename decltype(util::args(i.functor))::arg0>(json[i.key])); }); } }
ここで、util::argsはファンクタの引数を得るためのヘルパ:
template <class ...Args> struct parameter_pack {}; //型リストを比較する用 template <class F, class R, class ...Args> struct args_impl { args_impl(R(F::*)(Args...) const); args_impl(R(F::*)(Args...)); using arg0 = typename std::tuple_element<0, std::tuple<Args...>>::type; using pack = parameter_pack<Args...>; }; template <class F> struct args : decltype(args_impl(&F::operator())) { args(F); };
参照:
C++ のラムダ式の引数型を推論する - Secret Garden(Instrumental)
また、組(key, var, functor)を与えるための構造体は:
template <class T> struct identity_function { T operator()(T t) const { return t; } }; template <class S, class T, class F> struct v { S const key; T& var; F functor; v(S const s, T& t, F&& f = identity_function<T>{}) : key(s), var(t), functor(f) {} }; template <class S, class T, class F> v(S, T, F) -> v<S, T, F>; template <class S, class T> v(S, T) -> v<S, T, identity_function<T>>;
テストコード
int main() { std::string src = R"({"array1": [1, "one"], "array2": [[-1, -2], [-3, -4]], "id": 1})"; 省略 j.bind(std::tuple{v{"array1", a}, v{"array2", b}, v{"id", c, [](int x){return (ID)(100);}}}); std::cout << "------array1-------" << std::endl; std::cout << std::get<0>(a) << std::endl; std::cout << std::get<1>(a) << std::endl; std::cout << "------array2-------" << std::endl; for (auto const& ii : b) { for (auto const& i : ii) { std::cout << i << std::endl; } } std::cout << "------ID-------" << std::endl; std::cout << (int)c << std::endl;
結果
------array1------- 1 one ------array2------- -1 -2 -3 -4 ------ID------- 100
問題点1
ファンクタの引数のうち最初の1つしか得られない。
本当は
template <class std::size_t N> using arg = ...;
と書きたいが、うまくいかない…
問題点2
args周りが汚すぎる
今回分かったこと・疑問点
クラステンプレートの内部にエイリアステンプレートを書けない?
その解決策の1つに継承がある
C++分からん…入門すらできてないのがよく分かった(+_+)
次にやりたいこと
関数fから逆関数を生成(std::mapを使った限定的なもの)
bindに与えたリストを保存する
dump(bindの逆)を行う
#全体的に汚いのはなんとかしたい
#書いているときは気がつかなかったけど、使いどころがあまりない