tieで初期化させろ take 2

このような指令が来ましたので、やりましょう。


#include <utility>
#include <tuple>
#include <iostream>

#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/tuple/eat.hpp>
#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/repetition/for.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/facilities/is_empty.hpp>

template<std::size_t N, typename Tup>
typename std::tuple_element<N, Tup>::type &
get_with_tuple_ref_collapsing(Tup & tup) {
return std::get<N>(tup);
}
template<std::size_t N, typename Tup>
typename std::tuple_element<N, Tup>::type &&
get_with_tuple_ref_collapsing(Tup && tup) {
return std::move(std::get<N>(tup));
}

#define TIE(seq, expr) TIE_I(seq, expr, __LINE__,)
#define TIE_AUTO(seq, expr) TIE_I(seq, expr, __LINE__, auto)
#define TIE_I(seq, expr, id, a) TIE_II(seq, expr, id, a)
#define TIE_II(seq, expr, id, type) \
auto && tie_tmp_ ## id = expr \
BOOST_PP_FOR((tie_tmp_ ## id, type, 0, seq), TIE_P, TIE_OP, TIE_M)

#define TIE_P(_, state) BOOST_PP_SEQ_SIZE(BOOST_PP_TUPLE_ELEM(4, 3, state))
#define TIE_OP(_, state) TIE_OP_I state
#define TIE_OP_I(name, type, n, seq) \
(name, type, BOOST_PP_INC(n), BOOST_PP_SEQ_TAIL(seq))
#define TIE_M(_, state) TIE_M_I state
#define TIE_M_I(name, type, n, seq) \
TIE_M_II(name, type, n, BOOST_PP_SEQ_HEAD(seq))
#define TIE_M_II(name, type, n, e) \
BOOST_PP_IIF(TIE_IGNORE_P(e), BOOST_PP_TUPLE_EAT(1), ; type e) \
(get_with_tuple_ref_collapsing<n>(std::forward<decltype)((name))(>(name)))

#define TIE_IGNORE_P(name) BOOST_PP_IS_EMPTY(name)

int main()
{
TIE)((const int x)(const int y)(const int z), std::make_tuple(1, 2, 3))(;
std::cout << x << "," << y << "," << z << std::endl;

TIE)((const int a)(), std::make_tuple(4, 5))(;
std::cout << a << std::endl;
return 0;
}

TIE_IGNORE_Pを書き換えれば、お好きなキーワードでignore相当の機能を使うことができる親切設計。