4

私はzip関数を実装しようとしています。 zipのパラメータはそれぞれwrapped<Ti>で、Tiはパラメータによって異なります。const-correctnessを持つvariadic zip関数を実装しています

zipは、これらのwrapped<Ti>秒を取り、wrapped<tuple<T1&,T2&,...TN&>>を生成し、または他の言葉でそのパラメータへの参照のtupleを包みました。参照はconst -nessを保持する必要があります。ここで

は、一般的には動作しませんつのパラメータを持つzipで私の最初の刺し、です:

#include <utility> 
#include <tuple> 

// implement forward_as_tuple as it is missing on my system 
namespace ns 
{ 

template<typename... Types> 
    std::tuple<Types&&...> 
    forward_as_tuple(Types&&... t) 
{ 
    return std::tuple<Types&&...>(std::forward<Types>(t)...); 
} 

} 

template<typename T> 
    struct wrapped 
{ 
    wrapped(T &&x) 
    : m_x(std::forward<T>(x)) 
    {} 

    T m_x; 
}; 

template<typename T> 
    wrapped<std::tuple<T&&>> 
    zip(wrapped<T> &&x) 
{ 
    auto t = ns::forward_as_tuple(std::forward<T>(x.m_x)); 
    return wrapped<std::tuple<T&&>>(t); 
} 

int main() 
{ 
    wrapped<int> w1(13); 

    wrapped<int> &ref_w1 = w1; 

    // OK 
    zip(ref_w1); 

    const wrapped<int> &cref_w1 = w1; 

    // XXX won't compile when passing a const reference 
    zip(cref_w1); 

    return 0; 
} 

zipの単一バージョンで一般的な、可変引数の場合を実装する方法はありますか?

+0

これは、直接バインドされた参照が行う一時的な有効期間拡張の動作を持たないことを認識しています。 –

+2

"..."を振ると効果があります。 :-) –

+0

はい、OKです。 –

答えて

1

ここです私が到着した解決策:

#include <utility> 
#include <tuple> 
#include <cassert> 

template<typename T> 
    struct wrapped 
{ 
    wrapped(T &&x) 
    : m_x(std::forward<T>(x)) 
    {} 

    T m_x; 
}; 

template<typename Tuple> 
    wrapped<Tuple> make_wrapped_tuple(Tuple &&x) 
{ 
    return wrapped<Tuple>(std::forward<Tuple>(x)); 
} 

template<typename... WrappedTypes> 
    decltype(make_wrapped_tuple(std::forward_as_tuple(std::declval<WrappedTypes>().m_x...))) 
    zip(WrappedTypes&&... x) 
{ 
    return make_wrapped_tuple(std::forward_as_tuple(x.m_x...)); 
} 

int main() 
{ 
    wrapped<int> w1(1); 
    wrapped<int> w2(2); 
    wrapped<int> w3(3); 
    wrapped<int> w4(4); 

    auto z1 = zip(w1,w2,w3,w4); 

    z1.m_x = std::make_tuple(11,22,33,44); 

    assert(w1.m_x == 11); 
    assert(w2.m_x == 22); 
    assert(w3.m_x == 33); 
    assert(w4.m_x == 44); 

    const wrapped<int> &cref_w1 = w1; 

    auto z2 = zip(cref_w1, w2, w3, w4); 

    // does not compile, as desired 
    // z2.m_x = std::make_tuple(111,222,333,444); 

    return 0; 
} 

zipがの代わりにWrappedTypes...であることは、解決策として満足できるものではありませんが、機能します。

1

確かに、私は可変的なテンプレートを扱うC++ 0xコンパイラを持っていないので、私はそれをテストできません。しかし、これはトリックを行う可能性があります。

template<typename T> 
    struct wrapped 
{ 
    wrapped(T &&x) 
    : m_x(std::forward<T>(x)) 
    {} 

    typedef T type; 

    T m_x; 
}; 

template<typename... Types> 
    wrapped<std::tuple<Types&&...>> zip(wrapped<Types>&&... x) 
{ 
    return wrapped<std::tuple<Types&&...>>(std::tuple<Types&&...>(std::forward<Types>(x.m_x)...)); 
} 

私はこのようなzipを呼び出すことが合法であるならば、完全にはわからない:

zip(wrapped<T1>(value1), wrapped<T2>(value2)); 

あなたが明示的に呼び出しを修飾する必要がある場合があります

zip<T1, T2>(wrapped<T1>(value1), wrapped<T2>(value2)); 
+0

ありがとうございます、あなたのソリューションは非コンステートの場合に動作するようですが、コンパイラは 'const'リファレンスを' wrapper 'に 'zip'することを拒否します。明確にするために、私は 'zip'の引数に' const' -nessをミックスしてマッチさせたいと思います。これは可能ですか? –

0
template<typename T> 
    struct wrapped 
{ 
    wrapped(T &&x) 
    : m_x(std::forward<T>(x)) 
    {} 

    typedef T type; 

    T m_x; 
}; 

template<typename... Types> 
    wrapped<std::tuple<T&&...>> zip(wrapped<Types>... &&x) 
{ 
    return G+ 
関連する問題