5

私は可変個引数でいくつかの実験を行っていますが、解決策を理解できない問題に遭遇しました-基本的に私は任意のデータ型のコンポーネントでツリーを構築しようとしています-ここにいくつかのコードがあります:

template <class A, class B>
struct SeqExpression
{
    const A & first;
    const B & then;
};

template <class A, class B>
SeqExpression<A,B>
make_seq(const A & a, const B & b)
{
    return {a,b};
}

template <class A, class B, class ...T>
auto
make_seq(const A & first, const B & second, T ...rest) -> decltype(make_seq(make_seq(first,second),rest...))
{

    return make_seq(make_seq(first,second),rest...);
}

それから私は試します:

auto x = make_seq("X","Y",'z');

しかし、GCC(4.7)は私に次のように語っています。

error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting ‘template<class A, class B, class ... T> decltype (make_seq(make_seq(first, second), rest ...)) make_seq(const A&, const B&, T ...) [with A = SeqExpression<char [2], char [2]>; B = char; T = {}]’
recursively required by substitution of ‘template<class A, class B, class ... T> decltype (make_seq(make_seq(first, second), rest ...)) make_seq(const A&, const B&, T ...) [with A = SeqExpression<char [2], char [2]>; B = char; T = {}]’
required by substitution of ‘template<class A, class B, class ... T> decltype (make_seq(make_seq(first, second), rest ...)) make_seq(const A&, const B&, T ...) [with A = char [2]; B = char [2]; T = {char}]’

それは解決できるはずですが、私には思えます!

make_seq("X","Y")タイプSeqExpression< char[2],char[2] > があるのでmake_seq(make_seq("X","Y"),'z')タイプがありますSeqExpression< SeqExpression< char[2],char[2] >,char >

そしてそれは私には比較的非ループのようです。

何かご意見は?

4

1 に答える 1

3

問題は、(2つの引数のテンプレートに対して)2つの引数がある場合に、可変個引数テンプレートが選択されていることです。少なくとも3つの引数がある場合にのみ選択されるようにする必要があります。最も簡単な方法は、別の引数を追加することです。

template <class A, class B, class C, class ...T>
auto
make_seq(const A & first, const B & second, const C &third, T ...rest)
 -> decltype(make_seq(make_seq(first,second), third, rest...))
{

    return make_seq(make_seq(first,second), third, rest...);
}

可変個引数引数パックは、ゼロ引数と一致する可能性があります。意外に思われるかもしれませんが、他の方法よりも優れています。


明らかに、上記はリターンタイプの非標準のg++拡張を利用していることに注意してください。次のタイププログラムは、パラメータシーケンスに対応するタイプを計算できるはずです。

template <int n, class ...T> struct mst_helper;
template <class A, class B>
struct mst_helper<2, A, B> { typedef SeqExpression<A, B> type; };
template <int n, class A, class B, class ...T>
struct mst_helper<n, A, B, T...> {
    typedef typename mst_helper<n - 1, SeqExpression<A, B>, T...>::type type; };
template <class ...T>
struct make_seq_type { typedef typename mst_helper<sizeof...(T), T...>::type type; };

template <class A, class B, class C, class ...T>
typename make_seq_type<A, B, C, T...>::type
make_seq(const A & first, const B & second, const C &third, T ...rest)
{
    return make_seq(make_seq(first,second), third, rest...);
}

g ++-4.7.1にはテンプレートエイリアスのバグがあるようですので、structの代わりにを使用する必要がありusingました。

于 2012-08-17T11:57:27.287 に答える