2016-02-22 7 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. 

जब मैं स्पष्ट रूप से करने के लिए वस्तु डाली:

#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 सूचीबद्ध के आधार पर, मैं कोई कारण नहीं है कि यह काम नहीं करना चाहिए देखें। मुझे लगता है कि दोनों क्लैंग और जीसीसी ने एक ही चीज़ को खराब नहीं किया, इसलिए मुझे कल्पना है कि मुझे एक वैचारिक गलतफहमी मिली है। - टेम्पलेट तर्क कटौती अंतर्निहित रूपांतरण के माध्यम से नहीं लगती है

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); 

कटौती दूसरा तर्क के लिए विफल रहता है क्योंकि एक HasConversionToString एक std::basic_string नहीं है:

उत्तर

16

पर आप कॉल करना चाहते हैं एक समारोह टेम्पलेट है। नतीजतन, उस फ़ंक्शन टेम्पलेट को ओवरलोड रिज़ॉल्यूशन से हटा दिया गया है।

std::experimental::basic_string_view ऐसी ही समस्या है, जिसे "पर्याप्त अतिरिक्त अधिभार" नियम द्वारा हल किया गया था (पुस्तकालय में पर्याप्त अधिभार जोड़ना चाहिए ताकि basic_string_view और एक कार्य में परिवर्तनीय कुछ के बीच तुलना हो)।

आप वास्तव में basic_string के लिए ऐसी कोई चीज़ नहीं चाहते हैं, हालांकि < संभवतः चुपचाप ढेर की यात्रा के कारण वास्तव में एक अच्छा विचार नहीं है।

+0

क्या यह SFINAE का मामला है? – MtRoad

+1

@MtRoad यहां कोई प्रतिस्थापन नहीं है। –

+0

क्या इसके आसपास कोई सभ्य तरीका है? मैंने जानबूझकर रूपांतरण को एक कॉन्स वापस कर दिया और दुर्भाग्यपूर्ण अप्रत्याशित आवंटन से बचने के लिए। – David

4

http://en.cppreference.com/w/cpp/language/template_argument_deduction#Implicit_conversions

प्रकार कटौती अंतर्निहित रूपांतरण ( ऊपर सूचीबद्ध समायोजन प्रकार के अलावा अन्य) पर विचार नहीं करता: कि अधिभार संकल्प, जो बाद में होता है के लिए काम है।

संबंधित मुद्दे