0

次のコードをコンパイルしようとすると:

    #include <iostream>
    #include <set>
    #include <vector>

    using namespace std;

    template <class T, class S> 
    class Property
    {
    public:
        pair<T,S> p;

        Property(T t, S s) { p = make_pair(t,s);}

    };

    int main()
    {
    set< Property<string, string> > properties;
    Property<string, string> name("name", "Andy");

    properties.insert(name);

    }

コンパイルエラーが発生します。ただし、セットをベクターに置き換えて、挿入関数の代わりに push_back 関数を使用すると、すべて正常に機能します。誰かが私が間違っていることを説明できますか? アドバイスありがとう。

4

2 に答える 2

5

std::setソートされた二分木に値を格納するため、保持している値を比較する方法を知る必要があります。デフォルトではstd::less、特殊化されていないユーザー定義型に対して を呼び出そうとする比較関数として使用されますoperator<。したがって、オブジェクトを比較する方法をセットに伝える最も簡単な方法はoperator<、クラスに を定義することです。

template <class T, class S> 
class Property
{
public:
    pair<T,S> p;

    Property(T t, S s) { p = make_pair(t,s);}

    bool operator<(const Property<T,S>& rhs) const
    {
        return p < rhs.p;
    }
};

std::setただし、タイプを比較する方法は他にもあります。std::less1 つは、クラスのテンプレートを特殊化することです。

namespace std {
template<typename T,typename S>
struct less<Property<T, S> >
{
    bool operator()(const Property<T, S>& lhs, const Property<T,S>& rhs) const
    {
        return lhs.p < rhs.p;
    }
};
}

もう 1 つは、既定の比較型を、正しいシグネチャを持つ関数、または正しいシグネチャを持つoperator()定義済みのクラスに置き換えることです。これは、物事が醜くなり始めるところです。

// Comparison function
template<typename T, typename S>
bool property_less_function(const Property<T,S>& lhs, const Property<T,S>& rhs)
{
    return lhs.p < rhs.p;
}

// Comparison functor
template<typename T, typename S>
struct PropertyLess
{
    bool operator()(const Property<T,S>& lhs, const Property<T,S>& rhs) const
    {
        return lhs.p < rhs.p;
    }
};

int main()
{
    // Set using comparison function. 
    // Have to pass the function pointer in the constructor so it knows
    // which function to call. The syntax could be cleaned up with some
    // typedefs.
    std::set<Property<std::string, std::string>, 
        bool(*)(const Property<std::string, std::string>&, 
                const Property<std::string, std::string>&)> 
            set1(&property_less_function<std::string, std::string>);

    // Set using comparison functor. Don't have to pass a value for the functor
    // because it will be default constructed.
    std::set<Property<std::string, std::string>, PropertyLess<std::string, std::string> > set2;
}

どのような小なり関数を使用する場合でも、その関数は型の厳密な弱い順序付けを定義する必要があることに注意してください。

于 2013-02-09T05:09:08.917 に答える
2

に何かを挿入するには、定義std::setする必要があります。operator<

たとえば、これは GCC 4.7.2 で正常にコンパイルされます。

#include <iostream>
#include <set>
#include <vector>

using namespace std;

template <class T, class S> 
class Property
{
public:
    pair<T,S> p;
    Property(T t, S s) { 
        p = make_pair(t,s);
    }
    bool operator<(const Property& p2) const {
        //Something naive..
        return p < p2.p; 
    }

};

int main()
{
set< Property<string, string> > properties;
Property<string, string> name("name", "Andy");

properties.insert(name);

}

代わりに使用することstd::unordered_setもできますが、キーと定義のハッシュを提供する必要がありますoperator==

于 2013-02-09T03:39:16.993 に答える