日記

内容の正しさは保証しません

ノート 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の逆)を行う

#全体的に汚いのはなんとかしたい
#書いているときは気がつかなかったけど、使いどころがあまりない