4

我試圖實現zip函數。 zip的參數各爲wrapped<Ti>,其中Ti因參數而異。使用常量正確性實現可變參數壓縮函數

zip取這些wrapped<Ti>s併產生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

是的,沒關係。 –

回答

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...而不是wrapped<T>...不是滿意的解決方案,但它的工作原理。

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

謝謝,您的解決方案似乎適用於非''contst'的情況,但編譯器拒絕讓''將'const'引用壓縮到'wrapper'。爲了清楚起見,我想將參數中的'const'混合到'zip'中。這可能嗎? –

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+