6

我有一个包含 3 个字段的结构,两个ints (我们称它们为AB和一个bool ( C )

我想创建一种该结构的数组,并能够通过任何键(A 或 B)访问它,从而获得孔对象(带有 A、B 和 C)作为回报。如果这有什么不同的话,我不需要做类似“获取所有布尔为真的对象”之类的事情。

显然,两个键都是唯一的,而 bool 不能是唯一的,但为了清楚起见,我想我会提到它。

如果没有 A 或 B,那将是一个简单的std::map<int, bool>.

我目前看到的唯一解决方案是制作一个包含 2 sets 和 a的包装器vector。有什么方法可以让我的生活更轻松吗?

注意:它最多包含一百个元组,所以性能应该不是问题。线性访问是可以接受的。

为了更清楚,这就是我想做的事情:

foobar<int, int, bool> array;  // or something along those lines

array.add(1, 101, true);
array.add(2, 102, false);

array.getA(1); // returns first object
array.getA(2);   // returns second object
array.getB(102); // returns second object again
4

4 回答 4

6

我相信您正在寻找的是boost::multi_index。它允许您声明一个具有多个索引的容器。

struct MultiIDStruct
{
    size_t idA;
    size_t idB;
    std::string name;
};

namespace mul = boost::multi_index;

boost::multi_index_container< MultiIDStruct, 
    mul::indexed_by< 
        mul::ordered_unique< mul::member< MultiIDStruct, size_t, &MultiIDStruct::idA > >,
        mul::ordered_unique< mul::member< MultiIDStruct, size_t, &MultiIDStruct::idB > > 
    > > data;

(根据 Rapptz 的建议使用命名空间“快捷方式”)

例如,这里有一个multi_index容器,MultiIDStruct其中有两个唯一的排序,一个 on idA(它是 的成员MultiIDStruct)和第二个 on idB(它也是一个成员)。

模板参数一开始似乎很少,但一旦你了解了它们的工作原理,它们就不会那么糟糕了。

于 2013-06-30T01:02:49.667 回答
1

将它分成两个映射的建议当然更简单一些,但如果你想要更多的灵活性并且可以使用 C++11 来实现类似的功能std::tuple,你可以尝试以下形式:

#include <iostream>
#include <map>
#include <tuple>

template <typename T1, typename T2, typename T3>
class foobar
{
public:
    void add(T1 t1, T2 t2, T3 t3)
    {
        m1[t1] = std::make_tuple(t1, t2, t3);
        m2[t2] = std::make_tuple(t1, t2, t3);
    }

    std::tuple<T1,T2,T3> getA(T1 t1)
    {
        return m1[t1];
    }

    std::tuple<T1,T2,T3> getB(T2 t2)
    {
        return m2[t2];
    }

private:
    std::map<T1,std::tuple<T1,T2,T3>> m1;
    std::map<T2,std::tuple<T1,T2,T3>> m2;
};

int main()
{
    foobar<int, int, bool> array;  // or something along those lines

    array.add(1, 101, true);
    array.add(2, 102, false);

    auto res1 = array.getA(1); // returns first object
    auto res2 = array.getA(2);   // returns second object
    auto res3 = array.getB(102); // returns second object again

    std::cout << std::get<0>(res1) << std::endl;
    std::cout << std::get<1>(res2) << std::endl;
    std::cout << std::get<2>(res3) << std::endl;

    return 0;
}

一个工作示例给出了输出 1, 102, 0 (false)。

于 2013-06-30T01:01:54.693 回答
0

我知道我没有给出详细的实现。但我只是建议使用两张地图的逻辑。它出什么问题了?为什么我会被否决?

struct s
{
int i;
int j;
bool b;
};

std::map<int, int> mapA;
std::map<int, s> mapB;

const s& getA(int i)
{
    return mapB[mapA[i]];
}

const s& getB(int j)
{
    return mapB[j];
}

void add(int i, int j, bool b)
{
    s p;
    p.i=i;
    p.j=j;
    p.b=b;
    mapB[j]=p;
    mapA[i]=j;
}
于 2013-06-30T00:55:32.720 回答
0

有同样的问题,有不同的解决方案!

在 A 和 B 上有两个散列函数,给出 h1(A) 和 h2(B) 这样它们不会给出相等的值。例子:

uint32_t A;
uint32_t B;

uint64_t hashA(uint32_t value)
{ return ((uint64_t)value) << 32; }

uint64_t hashB(uint32_t value)
{ return (uint64_t)value; }

将所有内容放入 std::map 中,以便 hashA 和 hashB 具有相同的 bool 值。使用 hashA 或 hashB 访问它。

示例:A = 0x10000001,B = 0x20000002,C = 真

哈希A(A):0x1000000100000000哈希B(B):0x0000000020000002

地图:0x1000000100000000 -> 真 0x0000000020000002 -> 真

于 2016-08-22T12:08:06.490 回答