【问题标题】:Creating map entry using a user-defined conversion使用用户定义的转换创建地图条目
【发布时间】:2016-03-03 15:29:41
【问题描述】:

我有一个键类型 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)

这些方面有什么解决办法吗?

【问题讨论】:

  • 我认为fbm.insert( fbd );这一行实际上应该是:fbm.insert( static_cast&lt;FooBarPair&gt;(fbd) );

标签: c++ dictionary c++03


【解决方案1】:

添加缺少的operator &lt;

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

编辑更改 Q 后:

您必须将转换更改为

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

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

Demo

【讨论】:

  • 谢谢,但我不能使用emplace() -- C++03。我的地图类型也不正确。我刚刚修好了。
  • 您必须将转换更改为operator std::pair&lt;const FooBar, int&gt;() const(注意const 已删除并添加)。
  • 全球operator&lt; 成功了。出于兴趣,为什么非 const FooBar 会触发两个用户定义的转换?为什么不允许这样做?
【解决方案2】:

(至少有时),地图实现是/曾经是红黑树。要使地图插入工作,您的键类型需要支持比较 (operator &lt;)。对于您的空结构和您从它们创建的对,我看不到满足此要求。

所以作为第一次健全性检查,我会用

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

为了查看您的代码是否有其他问题。 如果还是不能编译,请检查std::pair&lt;&gt;是否支持比较。

此外,您无需自己对 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);
}

【讨论】:

  • 非常合理的建议 Herr/Frau BitTickler。你看起来像一个知识渊博、经验丰富的人......或女士:)
猜你喜欢
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
相关资源
最近更新 更多