使用用户定义的转换创建映射条目

时间:2016-03-03 15:29:41

标签: c++ dictionary c++03

我有一个键类型std::pair<Foo,Bar>和值in的地图,我希望通过将std::pair<std::pair<Foo,Bar> , int>对传递给插入函数来插入到地图中({ {3}})

struct Foo{};
struct Bar{};

typedef std::pair<Foo,Bar>        FooBar;
typedef std::pair<FooBar,int>     FooBarPair;
typedef std::map<FooBar,int>      FooBarMap;


struct FooBarData
{    
    operator const FooBarPair() const
    {
        return std::make_pair( std::make_pair( m_foo , m_bar ) , m_num );
    }

private:
    int     m_num;
    Foo     m_foo;
    Bar     m_bar;
};

int main()
{
    FooBarData  fbd;
    FooBarMap   fbm;

    fbm.insert( fbd );
}

clang错误消息

/usr/include/c++/v1/map:1041:9: note: candidate function not viable: no known conversion from 'FooBarData' to 'const value_type' (aka 'const pair<const key_type, mapped_type>') for 1st argument
    insert(const value_type& __v) {return __tree_.__insert_unique(__v);}
    ^
/usr/include/c++/v1/map:1050:14: note: candidate function template not viable: requires 2 arguments, but 1 was provided
    void insert(_InputIterator __f, _InputIterator __l)
         ^
/usr/include/c++/v1/map:1045:9: note: candidate function not viable: requires 2 arguments, but 1 was provided
    insert(const_iterator __p, const value_type& __v)

这些方面有什么问题吗?

2 个答案:

答案 0 :(得分:1)

添加缺失的operator <

另外,从转化运算符的返回类型中删除const

修改在您更改Q之后:

您必须将转换更改为

operator std::pair<const FooBar, int>() const

否则,它将需要2次用户转换,这是不允许的。

Demo

答案 1 :(得分:1)

(至少有时候),地图实现是红黑树。要使地图插入生效,您的密钥类型需要支持比较(operator <)。我不能看到你的空结构和你从它们创建的那对要满足这个要求。

所以作为第一次完整性检查,我会用

替换Foo和Bar结构
typedef int Foo;
typedef int Bar;

以查看您的代码是否有其他错误。 如果仍未编译,请检查std::pair<>是否支持比较。

此外,您可以简单地享受地图模板已经为您完成的操作,而不是自己输入FooBarPair。例如:

...
operator FooBarMap::value_type() { 
    ...
}

这是一个固定版本,编译:

#include <map>
struct Foo { int x; };
struct Bar {};

typedef std::pair<Foo, Bar>        FooBar;
typedef std::map<FooBar, int>      FooBarMap;

bool operator <(const FooBarMap::key_type&lhs, const FooBarMap::key_type& rhs)
{
    return lhs.first.x < rhs.first.x;
}

struct FooBarData
{
    operator FooBarMap::value_type() const
    {
        return FooBarMap::value_type(FooBarMap::key_type(m_foo, m_bar), m_num);
    }

private:
    int     m_num;
    Foo     m_foo;
    Bar     m_bar;
};

int main()
{
    FooBarData  fbd;
    FooBarMap   fbm;

    fbm.insert(fbd);
}