通过索引c ++ 11访问元组元素 [英] access tuple elements by index c++11
问题描述
这不是秘密, std :: get< i>(元组)
惹恼了许多程序员.
It's not secret, std::get<i>(tuple)
annoys many programmers.
相反,我想使用类似 tuple [i]
之类的东西.
Instead of it, I want use something like 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
?
Q: What's wrong this code? i.e this code is usable or not?
If is usable why isn't std::tuple
implemented like this?
推荐答案
我不确定您所遇到的具体问题是什么,但似乎您正在寻找一点方便.以下使用占位符(以 _1
开头)来简化代码:
I'm not really sure what the specific question in your case is, but it seems you are looking for a little bit of convenience. The following uses the placeholders (starting with _1
) to simplify your code:
#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>
派生的:)希望您喜欢它.
The trick here is to know that std::is_placeholder<T>
is guaranteed to be derived from std::integral_constant<int,N>
:) Hope you like it.
这篇关于通过索引c ++ 11访问元组元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!