4

I created a class which contains 3 elements of the same type (something like std::pair<T,std::pair<T,T>>). Moreover I prepared it for use for(auto&var:t) But I don't know if I did it safely.

template <class T>
class Troika
{
public:
  Troika(const T& f, const T& s, const T& t)
    :first(f), second(s), third(t) {}
  Troika(){}

  T first;
  T second;
  T third;


  typedef T* iterator;
  typedef const T* const_iterator;

  iterator begin() 
  {
    return &first;
  }
  const_iterator begin() const
  {
    return &first;
  }
  iterator end()
  {
    return &third+1;
  }
  const_iterator end() const 
  {
    return &third + 1;
  }
};

I mean about this part: return &third + 1;. I know that if somebody have not huge knowledge about arithmetic of pointers in c++, it is really dangerous. Are these elements alocated one by one near each other?

mvxxx
  • 115
  • 9
  • Possible duplicate of [Class contiguous data](https://stackoverflow.com/questions/4177346/class-contiguous-data) – Shubham May 22 '18 at 07:12

1 Answers1

10

Are these elements alocated one by one near each other?

They likely are, since they have the exact same accessibility. But it still doesn't make your implementation safe. Pointer arithmetic is only valid for elements in the same array object. Those three are not in the same array, there is no array in sight. Any attempt to use those iterators will result in undefined behavior.

I'm not sure of your intention in defining this class, but for a container of three elements of the same type, I'd offer the more idiomatic:

template<typename T>
using Troika = std::array<T, 3>;

You lose the first, second and third named members, but gain indexing (which is as good I think) and iteration for free.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    Can you explain what do you mean by "same array"? – Shubham May 22 '18 at 07:13
  • 1
    @Shubham - The same array, the same `T a[N];` – StoryTeller - Unslander Monica May 22 '18 at 07:13
  • And if you want `first`, `second` and `third`, you can inherit from `std::array` :P – Rakete1111 May 22 '18 at 07:15
  • 1
    "since they have the exact same accessibility" Really? So it's not because they are declared right after each other? If I put a private in the middle, the layout would change? – Rakete1111 May 22 '18 at 07:17
  • 2
    @Rakete1111 - Doesn't have to, but it may. [However, so long as the access control is the same, the addresses are sequential](https://timsong-cpp.github.io/cppwp/n4659/class.mem#17). – StoryTeller - Unslander Monica May 22 '18 at 07:18
  • @StoryTeller: Couldn't be easy to make by creating a unnamed `struct` instead of `std::array`, in the same place? something like `struct{ T first; T second; T third; }` . Then we can again follow the named members, right? just curious! – JeJo May 22 '18 at 08:12
  • @SaufenmitProgramming - I'm not sure I follow. If you replace the `std::array` by a class type, named or otherwise, you are back where the OP started. – StoryTeller - Unslander Monica May 22 '18 at 08:15
  • @StoryTeller Okay... I was also thinking whether its possible to get named members along with your std::array concept. thanks anyways. – JeJo May 22 '18 at 08:21
  • 1
    @SaufenmitProgramming You could always inherit from `std::array` and store named references to the array entries. Replicating the constructors may be annoying (and you would waste space) but it would definitely work just fine. – Max Langhof May 22 '18 at 08:52