2016-02-22 8 views
14

次のコードで暗黙的な変換が行われない理由を理解するのは苦労しています。私は明示的にオブジェクトをキャストすると、次のコードは正常に動作し、一方、比較で暗黙的な変換を伴うユーザー定義の変換を使用する

clang++ -std=c++14 -Wall -Wextra -pedantic conversion.cpp -o test 
conversion.cpp:13:12: error: invalid operands to binary expression ('string' (aka 'basic_string<char>') and 'HasConversionToString') 
    return s < obj; 
     ~^~~~ 
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_pair.h:220:5: note: candidate template ignored: could not match 
     'pair' against 'basic_string' 
    operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_iterator.h:298:5: note: candidate template ignored: could not match 
     'reverse_iterator' against 'basic_string' 
    operator<(const reverse_iterator<_Iterator>& __x, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_iterator.h:348:5: note: candidate template ignored: could not match 
     'reverse_iterator' against 'basic_string' 
    operator<(const reverse_iterator<_IteratorL>& __x, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_iterator.h:849:5: note: candidate template ignored: could not match 
     '__normal_iterator' against 'basic_string' 
    operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_iterator.h:856:5: note: candidate template ignored: could not match 
     '__normal_iterator' against 'basic_string' 
    operator<(const __normal_iterator<_Iterator, _Container>& __lhs, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_iterator.h:1089:5: note: candidate template ignored: could not match 
     'move_iterator' against 'basic_string' 
    operator<(const move_iterator<_IteratorL>& __x, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/stl_iterator.h:1095:5: note: candidate template ignored: could not match 
     'move_iterator' against 'basic_string' 
    operator<(const move_iterator<_Iterator>& __x, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/basic_string.h:4989:5: note: candidate template ignored: could not match 
     'basic_string<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>' against 'HasConversionToString' 
    operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/basic_string.h:5001:5: note: candidate template ignored: could not match 
     'const _CharT *' against 'HasConversionToString' 
    operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, 
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.3.0/../../../../include/c++/5.3.0/bits/basic_string.h:5013:5: note: candidate template ignored: could not match 
     'const _CharT *' against 'string' (aka 'basic_string<char>') 
    operator<(const _CharT* __lhs, 
    ^
1 error generated. 

:打ち鳴らすとgccの両方がの線に沿ってエラーで2つのオブジェクトを比較するための有効な方法を見つけるために失敗

#include <string> 
using namespace std; 

struct HasConversionToString { 
    HasConversionToString(const string& s_) : s{s_} {} 
    string s; 
    operator const string&() const { return s; } 
}; 

int main() { 
    string s{"a"}; 
    HasConversionToString obj{"b"}; 
    return s < obj; 
} 

文字列。

#include <string> 
using namespace std; 

struct HasConversionToString { 
    HasConversionToString(const string& s_) : s{s_} {} 
    string s; 
    operator const string&() const { return s; } 
}; 

int main() { 
    string s{"a"}; 
    HasConversionToString obj{"b"}; 
    return s < static_cast<string>(obj); 
} 

暗黙のキャストのためon cppreferenceを記載されているルールと例に基づいて、私はこれがうまくいかなければならない理由を見ません。私はclangとgccの両方が同じことを犯したとは思わないので、私は概念的な誤解があると想像します。 - 暗黙の変換に目を通していないテンプレート引数控除HasConversionToStringstd::basic_stringではないので

template<class charT, class Traits, class Alloc> 
bool operator<(std::basic_string<charT, Traits, Alloc> const& lhs, 
       std::basic_string<charT, Traits, Alloc> const& rhs); 

控除が第二引数に失敗:

答えて

16

あなたが呼び出したい1は、関数テンプレートです。その結果、その関数テンプレートは過負荷解決から削除されます。

std::experimental::basic_string_viewは「十分な追加のオーバーロード」ルールによって解決された同様の問題を持っている(ライブラリが十分なオーバーロードを追加する必要がありますように1つの作品に変換​​と何かとの比較)。

basic_stringのようなものは本当に必要ありませんが、恐らく<が黙ってヒープに移動しているのは本当に良い考えではありません。

+0

これはSFINAEのケースですか? – MtRoad

+1

@MtRoadここに代用はありません。 –

+0

これをまともな方法はありますか?私は故意に予期せぬ割り当てを避けるためにコンバートを返すコンバージョンを作った。 – David

関連する問題