Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有基于标识的等式的有序关联容器_C++_Templates - Fatal编程技术网

C++ 具有基于标识的等式的有序关联容器

C++ 具有基于标识的等式的有序关联容器,c++,templates,C++,Templates,我正在编写一个带有模板参数X的模板函数。在该函数中,我希望创建std::set,以便: 该集合中的对象按该对的第一个int字段进行排序,我不关心关系是如何断开的 我可以将多个具有相同的。第一个的对象添加到集合中,只要它们的。第二个对象不相同 若我知道模板参数X总是有简短的答案:使用std::multiset和sidestep-whole-issue-multiset允许多个键,那个么只需在对的第一个元素上进行比较 请注意,如果您想在地图中不允许相同的X值,您必须向X添加要求,因此它至少是相等可比

我正在编写一个带有模板参数X的模板函数。在该函数中,我希望创建std::set,以便:

该集合中的对象按该对的第一个int字段进行排序,我不关心关系是如何断开的 我可以将多个具有相同的。第一个的对象添加到集合中,只要它们的。第二个对象不相同
若我知道模板参数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>满足这两个条件

更新:由于可能没有,我认为::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>并在插入之前使用::std::find执行X的查找。虽然会慢一些。如果您正在编写一个模板,那么您可能希望为这两种情况编写专门化,并根据X是否有“是”使用集合或向量,但您的答案不同,您能更改它吗?这是误导;另外,如果您想使用向量集OP requested SET not map,那么我建议的multiset更好。X没有很好的运算符,那么您可以使用::std::map>并在插入之前使用::std::find执行X的查找。虽然会慢一些。如果您正在编写一个模板,那么您可能希望为这两种情况编写专门化,并根据X是否有“是”使用集合或向量,但您的答案不同,您能更改它吗?这是误导;另外,如果您想使用向量集OP requested SET not map,那么我建议的multiset更好。
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);
    }
};