web-dev-qa-db-ja.com

string_viewを使用したマップ検索

次のコードは、最近のコンパイラ(g ++-5.3、clang ++-3.7)ではビルドできません。

_#include <map>
#include <functional>
#include <experimental/string_view>

void f()
{
    using namespace std;
    using namespace std::experimental;
    map<string, int> m;
    string s = "foo";
    string_view sv(s);
    m.find(sv);
}
_

Clangから返されたエラー:

_error: no matching member function for call to 'find'
    m.find(sv);
    ~~^~~~
_

しかし、findは比較可能な型を使用できるべきではないのでしょうか? Cppreferenceは次のオーバーロードについて言及しています:

template< class K > iterator find( const K& x );

同じエラーが_boost::string_ref_でも発生します。

透明コンパレータ を明示的に指定する必要があります( std::less<> のように):

std::map<std::string, int, std::less<>> m;
//                         ~~~~~~~~~~^

std::map<K,V>はデフォルトでコンパレータを std::less<K> (つまり、non-transparentone)に、それ以降( [associative.reqmts]/p1 ):

メンバー関数テンプレートfindcountlower_boundupper_bound、およびequal_rangeは、qualified-idCompare::is_transparentは有効であり、タイプを示します(14.8.2)。

テンプレートメンバー関数findは実行可能な候補ではありません。

連想コンテナの異種比較ルックアップc ++ 14 に追加されました。元の提案では、既存のコードを壊す危険がありました。例えば:

c.find(x);

意味的には次と同等です:

key_type key = x;
c.find(key);

特に、xkey_typeの間の変換は、1回だけ、実際の呼び出しの前に発生します

異種ルックアップは、keyxの比較を優先して、この変換を置き換えます。これにより、既存のコードのパフォーマンスが低下する可能性があります(各比較の前に追加の変換が行われるため)、コンパイルが中断する可能性もあります(比較演算子がメンバー関数の場合、左側のオペランドには変換が適用されません)。

#include <set>
#include <functional>

struct A
{
    int i;

    A(int i) : i(i) {}
};

bool operator<(const A& lhs, const A& rhs)
{
    return lhs.i < rhs.i;
}

int main()
{
    std::set<A, std::less<>> s{{1}, {2}, {3}, {4}};
    s.find(5);
}

[〜#〜]デモ[〜#〜]

これを解決するために、 リンクされた質問 で説明されているように、透明なコンパレータの概念を追加することにより、新しい動作がオプトインされました。

33
Piotr Skotnicki