类似STL中pair的三元组类 - 我需要自己实现吗?

41

我想使用一个三元组类,尽可能类似于std::pair。STL似乎没有这样的类。我不想使用太重的东西,比如Boost。是否有某个有用的FOSS非限制性许可证的三元组类可以从其他地方借鉴?我应该自己编写吗?还是应该完全做其他事情?

编辑:关于std::tuple...

真的没有三元组特定类的好处吗?我的意思是,用tuple,我不能做到:

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

现在可以吗?我不需要为每种类型组合定义typedef吗?


3
我会选择使用 std::tuple - chris
3
如果由于某些原因您无法访问std::tuple(例如非符合C++11的编译器),请考虑使用std::pair<T,std::pair<U,V>> - Frédéric Hamidi
@FrédéricHamidi:这会使元素引用变得相当繁琐和不直观。 - einpoklum
2
但是使用 std::pair 时,元素引用已经不太直观了。你真的经常需要将元素称为 firstsecond(而不是例如 keyvalue,或者 namesurname)吗? - James Kanze
@einpoklum 确实如此。但这种情况很少适用。也许在某些数字应用中可以使用,但除此之外:最好直接表达语义意图。 - James Kanze
显示剩余2条评论
5个回答

56
不要自己造轮子,而是看看 std::tuple - 它是std::pair的一般化。这里有一个值初始化过的int三元组:
std::tuple<int, int, int> triple;

如果您希望,您可以仅为三元组创建一个类型别名:

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

谢谢。用了这个。不过,我觉得自己犯了罪。在想,如果使用一个结构体会更清晰一些。 - undefined

7

如果您能使用C++11,请使用std::tuple

如果不能,可以使用boost::tuple


6

如果你使用的是C++11,你可以使用std::tuple

如果你使用的是C++03,则需要自己实现(并不太难),或者使用来自Boost的tuple


4
我认为你需要这样的东西:
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;
}

使用示例:

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;

我正在使用这个,并且它对我的目的来说足够了...如果你想要不同类型的话,只需要进行一些修改:

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;
}

而且使用方法将非常相似:

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;

你的代码有一个小错误。make_triplet 的定义应该是 triplet<T1,T2,T3> make_triplet(const T1 &m1, const T2 &m2, const T3 &m3) - user1956185
当我使用以下代码时出现错误信息:vector< triplet<double, double, double> > v; v.emplace_back(1,2,3); - Neo li

-1
为了给std::pair添加相似性方面的特征,您可以定义一个具有first、second和third的类。我猜在这种情况下,您无法避免制作std::pair的子类并添加第三个成员。这只需要几行代码。
此外,如果您经常使用相同类型的这些内容,您还可以制作双胞胎和三胞胎类。使用C++-11的“using”很容易实现,例如:
template <typename T> using twins = std::pair<T,T>;

哦不,三元组类绝对不应该是std::pair的子类。三元组不是一种“一对”,就像std::pair<T,U>既不是T的子类也不是U的子类一样。 - einpoklum
我不明白你的观点。双胞胎是一对T和U属于相同类别的对象,三胞胎有3个相同类型的对象。任何三胞胎都可以替代任何双胞胎。 - Bert Bril
这绝对不是真的。使用一对数据,你依赖于恰好有两个数据;而使用三元组,则会做出矛盾的假设。它们不仅不能成为子类,而且也不能互换使用。 - einpoklum
抱歉,我不同意。在任何需要双体的地方,您都可以使用三体,但反之则不行。这正是继承的概念,LSK非常适用。此外,由于成员称为“第一”和“第二”参数化函数和类实际上只需要从一对中获取所需内容,即使它们实际上是在三元组上运行。非常标准且非常正确。 - Bert Bril

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接