2014-04-15 68 views
0

我嘗試參數(其可容納一個數組的引用)轉發到一個元組:傳遞一個數組作爲參照的std ::元組

#include <iostream> 
#include <tuple> 
#include <type_traits> 

#ifndef LOG_TYPE 
#define LOG_TYPE(X) std::clog << typeid(X).name() << std::endl; 
#endif 

#ifndef LOG 
#define LOG(X) std::clog << X << std::endl; 
#endif 

template <typename ... Parameters> 
void pass(Parameters&& ... parameters) { 
    auto tuple = std::forward_as_tuple(parameters ...); 

    // std::tuple<int (&) [3]> 
    LOG_TYPE(tuple); 

    typedef typename std::tuple_element<0, decltype(tuple)>::type array_type; 

    // int [3] 
    LOG_TYPE(array_type); 

    // --- The following is not the desired result ---  
    // array: 0 
    LOG("array: " << std::is_array<array_type>()); 
} 


template <typename ... Parameters> 
void pass_ref(Parameters&& ... parameters) { 
    auto tuple = std::forward_as_tuple(parameters ...); 

    // std::tuple<std::reference_wrapper<int [3]>&> 
    LOG_TYPE(tuple); 

    typedef typename std::remove_reference< 
     typename std::tuple_element<0, decltype(tuple)>::type>::type 
     element_type; 
    typedef typename element_type::type array_type; 

    // int [3] 
    LOG_TYPE(array_type); 

    // array: 1 
    LOG("array: " << std::is_array<array_type>()); 
} 


int main() { 
    int array[3]; 

    // array: 1 
    LOG("array: " << std::is_array<decltype(array)>()); 

    // This is what I like: 
    pass(array); 
    // This works: 
    pass_ref(std::ref(array)); 
    return 0; 
} 

是否有辦法來解決std::ref

(注:現在的問題是不是日誌記錄,但std::is_array<array_type>()

+2

無關:你可能要轉發的參數爲'forward_as_tuple',否則你轉發所有左值,它與'std :: tie'基本相同(所以你需要'std :: forward_as_tuple(std :: forward (parameters)...);')。 –

回答

1

forward_as_tuple建設對參數(link)和數組的引用引用的元組不是一個數組。您可以使用std::is_reference<T>進行檢查。

這似乎工作:

template <typename ... Parameters> 
void pass(Parameters& ... parameters) { 
        ^^^ no && 

    typedef std::tuple<Parameters...> tuple_type; 
    LOG_TYPE(tuple); 

    typedef typename std::tuple_element<0, tuple_type>::type array_type; 

    // int [3] 
    LOG_TYPE(array_type); 

    // array: 0 
    LOG("array: " << std::is_array<array_type>()); 
} 

您還可以修改原來的代碼砸參考:

template <typename ... Parameters> 
void pass(Parameters&& ... parameters) { 
    auto tuple = std::forward_as_tuple(parameters ...); 

    // std::tuple<int (&) [3]> 
    LOG_TYPE(tuple); 

    typedef typename std::tuple_element<0, decltype(tuple)>::type array_type_r; 

    // >>> drop the reference added by forward_as_tuple 
    typedef typename std::remove_reference<array_type_r>::type array_type; 

    // int [3] 
    LOG_TYPE(array_type); 

    // array: 0 
    LOG("array: " << std::is_array<array_type>()); 
} 
+0

謝謝雙方產生所需的結果 - 我會去第二 –

1
#define LOG_TYPE(X) std::clog << typeid(X).name() << std::endl; 

typeid是檢查這個錯誤的工具。

在第一個函數中,array_type不是數組類型,因爲它是引用類型。 tuple<int(&)[3]>的第一個元素是int(&)[3],而不是int[3]typeid不關心頂層引用,所以它不反映該程序的輸出。

當我調試模板元編程代碼以便說服編譯器輸出確切類型時,我傾向於使用類似於以下的構造。可悲的是,它只能作爲錯誤信息。

struct{}_ = foo; // where foo is a value of the type I want in the message 

這產生類似於「不從匿名結構轉換」的東西。有時候我沒有這個價值,因此我使用std::declval或簡單的template <typename T> struct show{};

所以你的解決方法是:

typedef typename std::remove_reference< 
    typename std::tuple_element<0, decltype(tuple)>::type>::type array_type;