2013-10-10 92 views
1

這不是祕密,std::get<i>(tuple)讓很多程序員很煩惱。通過索引C++訪問元組元素11

取而代之,我想用tuple[i]之類的東西。

所以我試圖模擬它。

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

template <int> struct index{}; 



template< char ... > 
struct combine; 

template<> struct combine<> : std::integral_constant< int , 0>{}; 


constexpr int ten(size_t p)noexcept 
{ 
    return p == 0 ? 1 : 10 * ten(p-1); 
} 

template< char c, char ... t> 
struct combine<c, t...> : std::integral_constant< int, (c - '0')*ten(sizeof...(t)) + combine<t...>::value > 
{ static_assert(c >= '0' && c <= '9', "only 0..9 digits are allowed"); }; 


template< char ... c > 
constexpr auto operator "" _index()noexcept 
{ 
    return index< combine<c...>::value >{}; 
}; 

template< class ... Args > 
struct mytuple : public std::tuple<Args...> 
{ 
    using std::tuple<Args...>::tuple; 

    template< int i > 
    auto& operator [](index<i>) noexcept 
    { 
     return std::get<i> (static_cast< std::tuple<Args...> & >(*this)); 
    } 

    template< int i> 
    auto const& operator [](index<i>)const noexcept 
    { 
     return std::get<i>(static_cast< std::tuple<Args...> const& >(*this)); 
    } 

}; 


int main() 
{ 
    static_assert(combine<'1','2','3','4'>::value == 1234, "!"); 


    static_assert(std::is_same< index<785>, decltype(785_index) > {}, "!"); 

    using person = mytuple< std::string, int, double, char>; 

    person s = std::make_tuple("Bjarne Stroustrup", 63, 3.14, '7'); 
    auto name = s[ 0_index ]; 
    auto old = s[ 1_index ]; 
    auto number = s[ 2_index ]; 
    auto symbol = s[ 3_index ]; 

    std::cout << "name: " << name << '\t' 
       << "old: " << old << '\t' 
       << "number: " << number<< '\t' 
       << "symbol: " << symbol<< '\t' 
       << std::endl; 
} 

問:這段代碼有什麼問題?即此代碼是否可用? 如果可以使用爲什麼不這樣執行std::tuple

+4

海事組織很少有這麼多的工作。我也認爲這個例子有一個錯誤。嘗試'0x1_index'或甚至'1.0_index'。 – Simple

+0

@簡單。謝謝。 –

+0

我也會說這不值得。 'std :: get (tuple)'這個令人討厭的事情是它不能與變量一起使用,而不能通過索引操作符來完成。您的實現仍然不提供通過簡單變量訪問元組。 –

回答

5

我不確定你的案例中的具體問題是什麼,但看起來你正在尋找一點便利。下面以佔位符(開始_1),以簡化代碼:

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

template< class ... Args > 
struct mytuple : public std::tuple<Args...> 
{ 
    using std::tuple<Args...>::tuple; 

    template< typename T > 
    auto& operator [](T) noexcept 
    { 
     return std::get< std::is_placeholder<T>::value - 1 >(*this); 
    } 

    template< typename T > 
    auto const& operator [](T) const noexcept 
    { 
     return std::get< std::is_placeholder<T>::value - 1 >(*this); 
    } 
}; 

int main() 
{ 
    using person = mytuple< std::string, int, double, char>; 

    using namespace std::placeholders; 

    person s = std::make_tuple("Bjarne Stroustrup", 63, 3.14, '7'); 
    auto name = s[ _1 ]; 
    auto old = s[ _2 ]; 
    auto number = s[ _3 ]; 
    auto symbol = s[ _4 ]; 

    std::cout << "name: " << name << '\t' 
       << "old: " << old << '\t' 
       << "number: " << number<< '\t' 
       << "symbol: " << symbol<< '\t' 
       << std::endl; 
} 

這裏的關鍵是要知道std::is_placeholder<T>保證從std::integral_constant<int,N>衍生:)希望你喜歡它。

+2

可惜它不是基於零的。 –

+0

在這種情況下'static_cast'是不必要的。 – Xeo

+0

這很好,但1)它不是基於零的。 2)最大_N - 由編譯器定義的實現。我並不感興趣如何實現這一點,我很有趣,爲什麼這種方式不流行或不被使用? –