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

Creating map entry using a user-defined conversion

我有一个键类型 std::pair<Foo,Bar> 和值 in 的映射,我想通过将对 std::pair<std::pair<Foo,Bar> , int> 传递给插入函数来将其插入到映射中,就像这样(online source)

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)

这些方面是否有任何修复?

补缺 operator <.

此外,从 return 类型的转换运算符中删除 const

编辑 Q:

您必须将转换更改为

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

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

Demo

(至少有时),地图实现 are/were 红黑树。要使地图插入工作,您的键类型需要支持比较 (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);
}