STL-pair-like triplet class - do I roll my own?
Asked Answered
J

5

42

I want to use a triplet class, as similar as possible to std::pair. STL doesn't seem to have one. I don't want to use something too heavy, like Boost. Is there some useful FOSS non-restrictive-license triplet class I could lift from somewhere? Should I roll my own? Should I do something else entirely?

Edit: About std::tuple...

Is there really no benefit to a triplet-specific class? I mean, with tuple, I can't do

template<typename T1, typename T2, typename T3> std::tuple<T1, T2, T3> triple;

now can I? Won't I have to typedef individual-type-combination triples?

Jew answered 20/12, 2013 at 14:23 Comment(7)
I'd say std::tuple.Schematize
If for some reason you do not have access to std::tuple (non-C++11 compliant compiler, for instance), consider std::pair<T, std::pair<U, V> >.Onionskin
@FrédéricHamidi: That would make element references quite cumbersome and uninituitive.Jew
But element references are already unintuitive with std::pair. How often do you really want elements called first and second (rather than e.g. key and value, or name and surname).Ciprian
@JamesKanze: mytriple.second.second is much more confusing than mytriple.third.Jew
@Jew True. But it's rare that either would be appropriate. Perhaps in some numeric applications, but otherwise: it's better to signal semantic intent directly.Ciprian
It is hilarious that, with all the talk (here and below) of convenience/inconvenience of accessing members of a std::tuple, nobody actually demonstrated the accessor syntax!Tekla
O
57

No, don't roll your own. Instead, take a look at std::tuple - it's a generalization of std::pair. So here's a value-initialized triple of ints:

std::tuple<int, int, int> triple;

If you want, you can have a type alias for triples only:

template<typename T1, typename T2, typename T3>
using triple = std::tuple<T1, T2, T3>;
Outherod answered 20/12, 2013 at 14:24 Comment(1)
Thanks. Used this. However, I feel like I have sinned. Wondering, if using a struct would have been cleaner.Bittersweet
X
7

If you can use C++11, use std::tuple

If not, use boost::tuple

Xhosa answered 20/12, 2013 at 14:24 Comment(0)
N
6

If you're using C++11, you can use std::tuple.

If you're using C++03, then you'll either need to resort to rolling your own (which isn't too hard), or using tuple from Boost.

Negativism answered 20/12, 2013 at 14:25 Comment(0)
R
4

I think you need something like this:

template<typename T>
struct triplet
{
    T first, middle, last;
};

template<typename T>
triplet<T> make_triplet(const T &m1, const T &m2, const T &m3) 
{
    triplet<T> ans;
    ans.first = m1;
    ans.middle = m2;
    ans.last = m3;
    return ans;
}

Examples of usage:

triplet<double> aaa;
aaa = make_triplet<double>(1.,2.,3.);
cout << aaa.first << " " << aaa.middle << " "  << aaa.last << endl;

triplet<bool> bbb = make_triplet<bool>(false,true,false);
cout << bbb.first << " " << bbb.middle << " "  << bbb.last << endl;

I'm using this and it is enough for my purposes... If you want different types, though, just do some modifications:

template<typename T1, typename T2, typename T3>
struct triplet
{
    T1 first; 
    T2 middle;
    T3 last;
};

template<typename T1, typename T2, typename T3>
triplet<T1,T2,T3> make_triplet(const T1 &m1, const T2 &m2, const T3 &m3) 
{
    triplet<T1,T2,T3> ans;
    ans.first = m1;
    ans.middle = m2;
    ans.last = m3;
    return ans;
}

And the usage will be very similar:

triplet<bool,string,myDouble> ccc;
ccc = make_triplet<bool,string,double>(false,"AB",3.1415);
ccc.middle = "PI";
cout << ccc.first << " " << ccc.middle << " "  << ccc.last << endl;
Reinsure answered 11/12, 2014 at 0:37 Comment(2)
There is a small mistake in your code. The definition of make_triplet should be triplet<T1,T2,T3> make_triplet(const T1 &m1, const T2 &m2, const T3 &m3)Ung
Get error message when I use: vector< triplet<double, double, double> > v; v.emplace_back(1,2,3);Simferopol
C
-1

To add the aspect of similarity to std::pair, you could define a class that has first, second and third. My guess is that in In that case you cannot avoid making a subclass of std::pair and add a 'third' member. It's a few lines of code.

Furthermore, if you often use these things with the same type, you could make twins and triplet classes as well. Easily made with C++-11's 'using', like:

template <typename T> using twins = std::pair<T,T>;
Chain answered 13/6, 2017 at 7:52 Comment(4)
Oh no, a triplet class should definitely not be a subclass of std::pair. A triplet is not a kind-of-a-pair, like a std::pair<T,U> is not a subclass of T nor of U.Jew
I don't see your point. A twin is a pair where Tand U are the same class, triplet has 3 of the same type. Any triplet can be usef where any twin can be usef.Chain
That is absolutely not true. With a pair, you rely on there being exactly two pieces of data; with a triplet, you make a contradictory assumption. Not only can they not be subclasses, but they cannot be used interchangeably.Jew
Sorry I disagree. Anywhere you need a twin you can use a triplet, but not the other way around. That's exactly the idea of inheritance, the LSK applies perfectly. Moreover, because the members are called 'first' and 'second' parameterized functions and classes get exactly what they need from a pair even when in fact they operate on a triplet. Very standard and very OK.Chain

© 2022 - 2024 — McMap. All rights reserved.