C++ 具有基于标识的等式的有序关联容器
我正在编写一个带有模板参数X的模板函数。在该函数中,我希望创建std::set,以便: 该集合中的对象按该对的第一个int字段进行排序,我不关心关系是如何断开的 我可以将多个具有相同的。第一个的对象添加到集合中,只要它们的。第二个对象不相同C++ 具有基于标识的等式的有序关联容器,c++,templates,C++,Templates,我正在编写一个带有模板参数X的模板函数。在该函数中,我希望创建std::set,以便: 该集合中的对象按该对的第一个int字段进行排序,我不关心关系是如何断开的 我可以将多个具有相同的。第一个的对象添加到集合中,只要它们的。第二个对象不相同 若我知道模板参数X总是有简短的答案:使用std::multiset和sidestep-whole-issue-multiset允许多个键,那个么只需在对的第一个元素上进行比较 请注意,如果您想在地图中不允许相同的X值,您必须向X添加要求,因此它至少是相等可比
若我知道模板参数X总是有简短的答案:使用std::multiset和sidestep-whole-issue-multiset允许多个键,那个么只需在对的第一个元素上进行比较 请注意,如果您想在地图中不允许相同的X值,您必须向X添加要求,因此它至少是相等可比较的。否则,您甚至无法检测X的值何时相同,何时不同 详细回答:
你的代码不会产生你所希望的结果。考虑添加新的对来映射。map将尝试使用的临时副本来查找的存在。它将使用x临时地址!,它将把false与map中的所有内容进行比较,std::map将根据x temporary!的地址找到要插入的位置!。然后它将复制x,从而改变地址并可能破坏自己的顺序。简短回答:使用std::multiset和sidestep整个问题-multiset允许多个键,所以只需在对的第一个元素上进行比较 请注意,如果您想在地图中不允许相同的X值,您必须向X添加要求,因此它至少是相等可比较的。否则,您甚至无法检测X的值何时相同,何时不同 详细回答: 你的代码不会产生你所希望的结果。考虑添加新的对来映射。map将尝试使用的临时副本来查找的存在。它将使用x临时地址!,它将把false与map中的所有内容进行比较,std::map将根据x temporary!的地址找到要插入的位置!。然后它将复制x,从而改变地址,并可能破坏其自身的顺序。我认为::std::map
更新:既然可能没有,你的问题是因为你担心X是一个虚拟成员函数吗?@xaxxon实际上,如果有帮助的话,我可以完全排除虚拟继承。我只是担心比较不平等的指针不是正确的习惯用法,所以奇怪的事情可能会发生。假设X是一些简单的东西,比如一对int,或者我定义的一个struct,等等。如果两个T*指针不同,那么它们引用不同的对象。另外,我说的是虚拟成员函数,而不是虚拟继承。如果其中一个是指向虚拟成员函数的指针,则结果是未指定的,即您在问题中输入的链接中调用的类型。该链接中的哪一部分内容让您对使用指针比较持谨慎态度?您可以散列X并将其用作排序吗?从X可以相等比较的事实来看,我假设它可以被散列。然后你就可以使用std::set从等价关系中生成一个排序在数学上是不可能的,所以你需要更多的信息,这是你的问题,因为你担心X是一个虚拟成员函数吗?@xaxxon实际上,如果有帮助的话,我可以完全排除虚拟继承。我只是担心比较不平等的指针不是正确的习惯用法,所以奇怪的事情可能会发生。假设X是一些简单的东西,比如一对int,或者我定义的一个struct,等等。如果两个T*指针不同,那么它们引用不同的对象。另外,我说的是虚拟成员函数,而不是虚拟继承。如果其中一个是指向虚拟成员函数的指针,则结果是未指定的,即您在问题中输入的链接中调用的类型。该链接中的哪一部分内容让您对使用指针比较持谨慎态度?您可以散列X并将其用作排序吗?从X可以相等比较的事实来看,我假设它可以被散列。到那时,您可以使用std::set从等价关系生成一个排序在数学上是不可能的,所以您需要更多的信息,不管怎样,我不清楚运算符==上的未指定行为是否有用。难道它不能总是返回真的吗?或者总是返回false?Quoting:当且仅当同一类型的两个指针都为null、都指向同一个函数或都表示同一地址时,才会比较相等。您正在将两个指针与X进行比较,这很好,因此当且仅当它们指向同一地址时,您才会得到true。从他提供的链接中可以看出:如果其中一个指针指向虚拟成员函数,则结果未指定。您没有比较指向虚拟成员函数的指针。你在比较
指向虚拟成员函数指针的指针。如果X是指向虚拟成员函数的指针,则与&X进行比较。因此,您将始终与指向对象的指针进行比较。指向指针的两个指针可能不同,但指向同一对象。你不是在比较X,而是在比较X*。我不清楚运算符==上的未指定行为是否有用。难道它不能总是返回真的吗?或者总是返回false?Quoting:当且仅当同一类型的两个指针都为null、都指向同一个函数或都表示同一地址时,才会比较相等。您正在将两个指针与X进行比较,这很好,因此当且仅当它们指向同一地址时,您才会得到true。从他提供的链接中可以看出:如果其中一个指针指向虚拟成员函数,则结果未指定。您没有比较指向虚拟成员函数的指针。您正在将指针与指向虚拟成员函数的指针进行比较。如果X是指向虚拟成员函数的指针,则与&X进行比较。因此,您将始终与指向对象的指针进行比较。指向指针的两个指针可能不同,但指向同一对象。您不是在比较X,而是在比较X*。X没有很好的运算符,那么您可以使用::std::map
template <typename X>
struct DistCmp {
bool operator()(const std::pair<int, X>& lhs, const std::pair<int, X>& rhs) const {
return lhs.first < rhs.first || lhs.first == rhs.first && &lhs.second < &rhs.second;
}
};
template <typename X>
void f() {
std::set<std::pair<int, X>, DistCmp<X>> s{};
// ...
}
#include <map>
#include <set>
#include <vector>
#include <type_traits>
#include <algorithm>
#include <utility>
// Default implementation is used when there is no < operator to compare T instances,
// but there is == operator.
template< typename T, typename TDummy = void >
t_FancyContainerHelper final
{
public: using
t_Values = ::std::vector< T >;
public: using
t_IntToValues = ::std::map< int, t_Values >;
public: static void
Insert(t_IntToValues & int_to_values, int const key, T const & value)
{
auto p_pair{int_to_values.find(key)};
if(int_to_values.end() != p_pair)
(
auto const & values(p_pair->second);
if(values.end() != ::std::find(values.begin(), values.end(), value))
{
return;
}
}
else
{
p_pair = int_to_values.emplace
(
::std::piecewise_construct
, ::std::forward_as_tuple(key)
, ::std::forward_as_tuple()
).second;
}
auto & values(p_pair->second);
values.emplace(value);
}
};
// This specialization is used when there is < operator to compare T instances.
template< typename T > class
t_FancyContainerHelper
<
T
, ::std::enable_if_t
<
::std::is_same
<
bool
, decltype
(
::std::declval< T const & >()
<
::std::declval< T const & >()
)
>
>
> final
{
public: using
t_Values = ::std::set< T >;
public: using
t_IntToValues = ::std::map< int, t_Values >;
public: static void
Insert(t_IntToValues & int_to_values, int const key, T const & value)
{
auto p_pair{int_to_values.find(key)};
if(int_to_values.end() != p_pair)
(
auto const & values(p_pair->second);
if(values.end() != values.find(value))
{
return;
}
}
else
{
p_pair = int_to_values.emplace
(
::std::piecewise_construct
, ::std::forward_as_tuple(key)
, ::std::forward_as_tuple()
).second;
}
auto & values(p_pair->second);
values.emplace(value);
}
};