2013-05-07 91 views
2

以下最小示例編譯與g++ -std=c++11 -Wall tuple.cpp -o tuple訪問元組元素中經由編譯時間變量C++ 11在功能

#include <tuple> 
#include <iostream> 

template<int i> 
char get_elem_i(std::tuple<char, char> t) 
{ 
    return std::get<i>(t); 
} 

int main() 
{ 
    std::tuple<char, char> t('H','i'); 
    char c = get_elem_i<0>(t); 
    std::cout << "The char is: " << c << std::endl; 
} 

現在,我不想使用模板指定的索引(確切的原因爲什麼:我有自動推導出的模板,我不想將它們全部指定)。所以我的第一次嘗試是:

char get_elem_i(int i, std::tuple<char, char> t) 
{ 
    return std::get<i>(t); 
} 

據我所知,這不能編譯。有沒有什麼辦法可以保證編譯器在編譯時會知道i?也許這樣?

char get_elem_i(compile_time_known int i, std::tuple<char, char> t) 

回答

3

你可以使用一個std::array代替std::tuple。在給出的例子中,元組的成員都具有相同的類型。

所以,我們可以這樣做:

char get_elem_i(int i, std::array<char, 2> t) 
{ 
    return t[i]; 
} 

這裏有你給說明爲什麼它在一般情況下是不能直接的例子有輕微的變體:

???? get_elem_i(int i, std::tuple<char, struct foo, class bar> t) { 
    return std::get<i>(t); 
} 

是什麼該函數的返回類型? charstruct foo


而你總是可以寫這樣的功能:

char get_elem_i(int i, std::tuple<char, char> t) { 
    switch (i) { 
     case 0: return std::get<0>(t); 
     case 1: return std::get<1>(t); 
    } 

    assert(false); 
} 
+0

」該函數的返回類型是什麼?「我會說這實際上不是問題 - 你可以使用'auto ... - > decltype(...)'類型的函數聲明來解決這個問題。問題是'int i'參數被用作'std :: get '中的模板參數。 – 2013-05-07 17:28:45

+1

@TimothyShields:當然,decltype的結果是什麼?一個變種? __reason__表示'i'是一個模板參數,因爲'std :: get'的返回類型根據該輸入而變化。 – 2013-05-07 17:30:29

+0

@TimothyShields:我也同意我的中間函數不能編譯。這是爲了解釋在一般情況下'i'需要成爲模板參數。 – 2013-05-07 17:32:26

1

如果你能知道的i在編譯的時候,那麼你可以讓周圍指定由包指定的i明確值的數值您邏輯iconstexpr

例如:

#include <tuple> 
#include <iostream> 

constexpr int compile_time_known_i(int input) { return input/3; } 

template<int i> 
char get_elem_i(std::tuple<char, char> t) 
{ 
    return std::get<i>(t); 
} 

int main() 
{ 
    std::tuple<char, char> t('H','i'); 
    char c = get_elem_i<0>(t); 
    char d = get_elem_i<compile_time_known_i(3)>(t); 
    std::cout << "The char is: " << c << " " << d << std::endl; 
} 

鑑於你i的可以在編譯時已知,這可能有助於乾淨的東西了(雖然多少感覺這使得取決於你的使用情況)。

如果是傳遞參數的語法,那麼您可以使用預處理器來實現此目的 - 具有一些可選的安全性type_traits

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

#define get_elem_i_ct(i, t)                \ 
    std::get<i>(t);                  \ 
    static_assert(std::is_integral<decltype(i)>::value, #i " must be an integral type"); \ 
    static_assert(std::is_same<decltype(t), std::tuple<char, char>>::value, #t " must be a tuple"); 

int main() 
{ 
    std::tuple<char, char> t('H','i'); 
    char c = get_elem_i_ct(0, t) 
    char d = get_elem_i_ct(1, t) 
    std::cout << "The char is: " << c << " " << d << std::endl; 
} 

雖然這達到了規定要求的語法,我不建議使用在憤怒這種方式 - 幾乎可以肯定有一個更好的解決您的實際問題。 「

+0

謝謝,但是這仍然需要一個模板參數。是不可能不使用? – Johannes 2013-05-07 17:50:20

+0

我已經更新了答案,以提供一種可能的方法。 – cmh 2013-05-08 10:25:20

+0

我不想使用宏。但這很有趣,謝謝! – Johannes 2013-05-08 18:45:53