使用用户定义的转换创建映射条目
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 次用户转化,这是不允许的。
(至少有时),地图实现 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);
}
我有一个键类型 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 次用户转化,这是不允许的。
(至少有时),地图实现 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);
}