@Jonathan Wakely によって 1 つの解決策が提供され、has_XXX
メタ関数の使用が採用されています。
ここに別の解決策がありますが、完全な構造体定義を の単なる typedef に変更する必要がありますstd::tuple<>
。
本格的な構造体:
struct case_0 { const char *foo; };
struct case_1i { const char *foo; int v0; };
struct case_1d { const char *foo; double v0; };
struct case_2ii { const char *foo; int v0; int v1; };
struct case_2id { const char *foo; int v0; double v1; };
次のように typedefs 構造体に置き換えられます。
typedef std::tuple<const char*> case_0;
typedef std::tuple<const char*,int> case_1i;
typedef std::tuple<const char*,double> case_1d;
typedef std::tuple<const char*,int,int> case_2ii;
typedef std::tuple<const char*,int,double> case_2id;
template<typename...Args>
auto foo(std::tuple<Args...> & tpl) -> decltype(std::get<0>(tpl))&
{
return std::get<0>(tpl);
}
template<typename...Args>
auto v0(std::tuple<Args...> & tpl) -> decltype(std::get<1>(tpl))&
{
return std::get<1>(tpl);
}
template<typename...Args>
auto v1(std::tuple<Args...> & tpl) -> decltype(std::get<2>(tpl))&
{
return std::get<2>(tpl);
}
そして使い方
case_1i obj; //full-fledge struct
obj.foo = "hello";
obj.v0 = 100;
に置き換えられます
case_1i obj; //typedef struct
foo(obj) = "hello";
v0(obj) = 100;
この設計変更を受け入れると、元の問題の解決策は次のように非常に簡単になります。
template<size_t...>
struct seq{};
template<size_t M, size_t ...N>
struct genseq : genseq<M-1,M-1, N...> {};
template<size_t ...N>
struct genseq<0,N...>
{
typedef seq<N...> type;
};
template <typename ...Args, size_t ...N>
void call_do_stuff_with(std::tuple<Args...> & tpl, seq<N...>)
{
do_stuff_with(std::get<N>(tpl)...);
}
template <typename ...Args>
void process(std::tuple<Args...> & tpl)
{
const size_t N = sizeof ...(Args);
call_do_stuff_with(tpl, typename genseq<N>::type());
}
それが受け入れられるかどうか教えてください。それが受け入れられない場合は、回答を削除します (そう思われる場合)。
ライブデモ!