此代码有效:
class MyObj {};
class MyData {
public:
using tMyMap = std::map<uint64_t, std::shared_ptr<MyObj>>;
const tMyMap& get_normal() const;
const tMyMap& get_reverse() const;
private:
std::map<uint64_t, std::shared_ptr<MyObj>> _normal;
std::map<uint64_t, std::shared_ptr<MyObj>, std::less<uint64_t>> _reverse;
};
const MyData::tMyMap& get_normal() const { return _normal; }
const MyData::tMyMap& get_reverse() const { return _reverse; }
但是clang-tidy建议我使用透明函子,并在声明std::less<uint64_t>
中将std::less<>
更改为_reverse
。不幸的是,当我这样做时,代码不再编译了:
test_map.cpp: In member function ‘const tMyMap& MyData::get_reverse() const’:
test_map.cpp:20:60: error: invalid initialization of reference of type ‘const tMyMap& {aka const std::map<long unsigned int, std::shared_ptr<MyObj> >&}’ from expression of type ‘const std::map<long unsigned int, std::shared_ptr<MyObj>, std::less<void> >’
const MyData::tMyMap& MyData::get_reverse() const { return _reverse; }
该错误消息来自g ++,但是clang给了我类似的错误。
为什么键入的函子可以,但是透明函子不能编译?
答案 0 :(得分:2)
std::map
's default comparator is std::less<KeyType>
.
This means that
std::map<uint64_t, T>
and
std::map<uint64_t, T, std::less<uint64_t>>
are the same type, but
std::map<uint64_t, T, std::less<>>
is a different type because std::less<uint64_t>
and std::less<>
are different types.
You would see the same issue if _normal
and _reverse
were actually the reverse of each other. I assume you actually meant to declare _reverse
as
std::map<uint64_t, std::shared_ptr<MyObj>, std::greater<uint64_t>> _reverse;
so that it's ordered in the opposite direction from _normal
.
答案 1 :(得分:1)
The problem is that the comparison function is part of the type of an instance of the std::map
template. The default value for the comparison function used by an std::map<K, T>
is std::less<T>
. So
std::map<uint64_t, std::shared_ptr<MyObj>, std::less<uint64_t>>
and
std::map<uint64_t, std::shared_ptr<MyObj>>
happen to be the same type (the second version will use the default argument for the comparison function, which comes out to be std::less<uint64_t>
). However, if you use std::less<>
(which is equivalent to std::less<void>
) as your comparison function for _reverse
, then the types of _normal
and _reverse
will not turn out the same anymore. Only _normal
will still be of type tMyMap
, which uses the default comparison function, while _reverse
will be a different, unrelated type.
If the purpose of MyData
is simply to hold these two maps, you might want to consider just turning it into a struct:
struct MyData {
std::map<uint64_t, std::shared_ptr<MyObj>> normal;
std::map<uint64_t, std::shared_ptr<MyObj>, std::less<>> reverse;
};
Or just use auto
to avoid having to repeat the type of each map
class MyData {
public:
const auto& get_normal() const { return _normal; }
const auto& get_reverse() const { return _reverse; }
private:
std::map<uint64_t, std::shared_ptr<MyObj>> _normal;
std::map<uint64_t, std::shared_ptr<MyObj>, std::less<>> _reverse;
};