0

そのように定義されたキャッシュの実装がありました。

std::vector<TEntryPair>    m_listEntries;

TEntryPairとして定義されています。

typedef std::pair<std::string, FILETIME> TEntryPair;

新しいレコードをキャッシュに挿入するときstd::lower_bound、次のように挿入ソート用のキャッシュ内の正しい場所を見つけるために使用します。

void AddCacheEntry(std::string const& strResourceName, FILETIME const& fTime)
{
    auto it = std::lower_bound(std::begin(m_listEntries),
                               std::end(m_listEntries),
                               strName);

    m_listEntries.insert(it, std::make_pair(strName, fTime));
}

新しいエントリはパラメータに基づいて挿入ソートされstd::string、2 番目の値は基本的にメタデータです。

std::lower_bound新しいレコードを挿入しようとするときに使用するために、次の演算子を定義しました。

bool operator < (std::string const& str, TEntryPair const& rhs)
{
    return str < rhs.first;
}
bool operator < (TEntryPair const& lhs, std::string const& str)
{
    return lhs.first < str;
}

TEntryPairの定義を次のように変更する必要があるまで、これはすべて正常に機能します。

std::pair<std::string, double>

std::pair<std::string, double>とは対照的に、私が定義した演算子を使用するときに使用できない理由を誰かが説明できますかstd::pair<std::string, FILETIME>?

コンパイラは次のエラーを返します。

Error   9   error C2676: binary '<' : 'std::pair<_Ty1,_Ty2>' does not define this operator or a conversion to a type acceptable to the predefined operator  c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   3   error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'std::pair<_Ty1,_Ty2>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   7   error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'std::pair<_Ty1,_Ty2>'    c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   2   error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'std::pair<_Ty1,_Ty2>'   c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   4   error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'std::pair<_Ty1,_Ty2>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   5   error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'std::pair<_Ty1,_Ty2>'   c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   8   error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const std::string' c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   6   error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'std::pair<_Ty1,_Ty2>'  c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736
Error   1   error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'std::pair<_Ty1,_Ty2>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm    2736

余談ですが、次のように定義して、エラーなしでコードをコンパイル/実行できます。

struct STemp
{
    double m_Value;
}

typedef std::pair<std::string, STemp> TEntryPair;

問題があるのは「基本的な」タイプだけのようですか?

4

1 に答える 1

3

原因は、標準ライブラリで定義済みの operator< と組み合わされた C++ の名前解決 (具体的には、引数依存のルックアップ) にあるようです。

TEntryPair が完全に標準ライブラリに配置されている場合、最上位の名前空間の operator< は見つかりません (名前空間 std の外に operator< への引数がないため、名前空間 std のみが引数依存のルックアップと見なされます)。

標準では、名前空間 std で関数をオーバーロードすることは許可されていないと明示的に述べられていますが、私が見つけた問題の唯一の解決策は、名前空間 std 内から operator< を呼び出しているため、operator< を名前空間 std に配置することです。 、引数はすべて名前空間 std に属します。

標準に準拠したソリューションの場合、std::pair を使用する代わりに独自のクラスを定義する必要があるでしょう。

#include <vector>
#include <algorithm>
#include <string>

typedef double MyType;

struct TEntryPair {
    std::string first;
    MyType second;
};

bool operator < (std::string const& str, TEntryPair const& rhs)
{
    return str < rhs.first;
}
bool operator < (TEntryPair const& lhs, std::string const& str)
{
    return lhs.first < str;
}

std::vector<TEntryPair>    m_listEntries;

void AddCacheEntry(std::string const& strResourceName, MyType fTime)
{
    auto it = std::lower_bound(std::begin(m_listEntries),
                               std::end(m_listEntries),
                               strResourceName);
}

int main() { }
于 2013-11-25T16:52:04.480 に答える