Overloading subscript operator

Hi, I would like to overload the subscript operator so that I can use tuples like an array
e.g.
mytuple[0];

Here is what I've coded, but I am new to using templates so I don't know what is happening, could someone tell me what I'm doing wrong & what should be done?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <tuple>

template <typename T>
T tuple::operator[](const int index) {
return get<index>(tuple);
}
...

int main() 
{
    int a=14;
    tuple<int,string,char> myTuple;
    myTuple[0]=1;
    a=myTuple[0];
    ...
return 0;
You can't. See SO for why: https://stackoverflow.com/questions/32606464/why-can-we-not-access-elements-of-a-tuple-by-index

(You have also chosen one of the most complex classes in the Standard Library to dink with.)

Hope this helps.
> Hi, I would like to overload the subscript operator so that I can use tuples like an array
> e.g. mytuple[0];

This is possible only if the index is an integral constant expression wrapped in a template.

A la place holders for std::bind():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <tuple>
#include <string>

namespace my
{
     template < std::size_t N > struct index {} ;

     template< typename... T > struct tuple : std::tuple<T...>
     {
         using std::tuple<T...>::tuple ;

         template < std::size_t N > constexpr decltype(auto) operator[] ( index<N> )
         { return std::get<N>(*this) ; }

         template < std::size_t N > constexpr decltype(auto) operator[] ( index<N> ) const
         { return std::get<N>(*this) ; }
     };

     constexpr index<0> _0 {} ; constexpr index<1> _1 {} ;
     constexpr index<2> _2 {} ; constexpr index<3> _3 {} ; // etc

     // TO DO: make_my_tuple etc.
}

int main()
{
    using namespace my ;

    tuple< int, std::string, const char*, char > my_tup {} ;

    my_tup[_0] = 1;
    my_tup[_1] = " hello" ;
    my_tup[_2] = " world" ;
    my_tup[_3] = '!' ;

    std::cout << my_tup[_0] << my_tup[_1] << my_tup[_2] << my_tup[_3] << '\n' ;
}

http://coliru.stacked-crooked.com/a/82b4d508ebc97ebf
Another very similar approach.
Wrote this out earlier today, but never posted it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# include <tuple>
# include <type_traits>

namespace my {
    template <typename... Ts> class tuple: public std::tuple<Ts...> {
        using base = std::tuple<Ts...>;
    public:
        using base::base;
        
        template <std::size_t I>
        constexpr decltype(auto) 
        operator[](std::integral_constant<std::size_t, I>) 
        { return std::get<I>(*this); }
    };
    
    template <typename... Args>
    tuple(Args...) -> tuple<Args...>;
    
    template <int I> 
    constexpr auto size_t_c = std::integral_constant<std::size_t, I>{};
}

# include <iostream>

int main() {
    my::tuple t{1, "hello!", 25.3, 4};
    std::cout << t[my::size_t_c<1>] << '\n';
}


http://coliru.stacked-crooked.com/a/bc96651e1a996495

I was also going to add that it is mostly prohibited to add behavior to the standard library. This is at least because the implementation may rely on the interface to select the correct behavior.
Last edited on
Topic archived. No new replies allowed.