次のコードは、最近のコンパイラ(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 ):
メンバー関数テンプレート
find
、count
、lower_bound
、upper_bound
、およびequal_range
は、qualified-idCompare::is_transparent
は有効であり、タイプを示します(14.8.2)。
テンプレートメンバー関数find
は実行可能な候補ではありません。
連想コンテナの異種比較ルックアップ が c ++ 14 に追加されました。元の提案では、既存のコードを壊す危険がありました。例えば:
c.find(x);
意味的には次と同等です:
key_type key = x;
c.find(key);
特に、x
とkey_type
の間の変換は、1回だけ、実際の呼び出しの前に発生します。
異種ルックアップは、key
とx
の比較を優先して、この変換を置き換えます。これにより、既存のコードのパフォーマンスが低下する可能性があります(各比較の前に追加の変換が行われるため)、コンパイルが中断する可能性もあります(比較演算子がメンバー関数の場合、左側のオペランドには変換が適用されません)。
#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);
}
これを解決するために、 リンクされた質問 で説明されているように、透明なコンパレータの概念を追加することにより、新しい動作がオプトインされました。