जीसीसी में अस्पष्ट ऑपरेटर


13

मैंने कुछ स्टाल कंटेनरों की छपाई के लिए एक फंक्शन टेम्प्लेट बनाया

#include <iostream>
#include <vector>
#include <string>

template <template <typename, typename> class C, typename T, typename A>
std::ostream& operator<<(std::ostream& os, const C<T, A>& container)
{ 
    for (auto& elem : container) 
    { 
        os << elem << " "; 
    } 

    return os; 
}

int main()
{
    std::vector<std::string> v { "One", "Two", "Three" };

    std::cout << v << std::endl;

    return 0;
}

यह MSVC, क्लैंग और ICC पर अपेक्षित रूप से संकलित और काम करता है, लेकिन जब GCC (ट्रंक) के साथ संकलित करता है, तो यह operator<<लाइन के लिए एक अस्पष्ट त्रुटि देता है os << elem << " "। और यहां तक ​​कि यह त्रुटि केवल ध्वज के साथ संकलन करते समय प्रकट होती है -std=c++17या -std=c++2a

त्रुटि उचित प्रतीत होती है std::string, क्योंकि, कंपाइलर एक मौजूदा फ़ंक्शन टेम्प्लेट का पता लगाता है जो वैश्विक के लिए operator<<एक आउटपुट स्ट्रीम और ए को स्वीकार करता है basic_string<CharT, Traits, Allocator>, जिस Allocatorप्रकार को डिफ़ॉल्ट किया जा रहा है std::allocator

मेरा प्रश्न यह होगा कि यह अन्य 3 संकलकों के साथ क्यों संकलित और काम करता है, मेरी समझ से, क्लैंग कम से कम, एक ही मानक पुस्तकालय कार्यान्वयन को gcc के रूप में उपयोग करता है, इसलिए इसमें समान फ़ंक्शन टेम्पलेट है operator<<

रिपोर्ट की गई त्रुटि है

error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'const std::__cxx11::basic_string<char>')

और दो उम्मीदवार

note: candidate: 'std::ostream& operator<<(std::ostream&, const C<T, A>&) [with C = std::__cxx11::basic_string; T = char; A = std::char_traits<char>; std::ostream = std::basic_ostream<char>]'

note: candidate: 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'

जीसीसी, क्लैंग और आईसीसी के लिए संकलक तर्क

-std=c++2a -O3 -Wall -Wextra -Wpedantic -Werror

MSVC के लिए एक

/std:c++latest /O2 /W3

अनिवार्य Godbolt लिंक: https://godbolt.org/z/R_aSKR

जवाबों:


8

त्रुटि उचित प्रतीत होती है std::string, क्योंकि, कंपाइलर एक मौजूदा फ़ंक्शन टेम्प्लेट का पता लगाता है जो वैश्विक के लिए operator<<एक आउटपुट स्ट्रीम और ए को स्वीकार करता है basic_string<CharT, Traits, Allocator>, जिस Allocatorप्रकार को डिफ़ॉल्ट किया जा रहा है std::allocator

C<T, A>एक प्रकार की तरह एक पैरामीटर से मेल करने की यह क्षमता basic_string<CharT, Traits, Allocator=std::allocator<CharT>>C ++ 17 में नई है, यह P0522 से आती है । उस कागज से पहले, आपके ऑपरेटर को उम्मीदवार के रूप में नहीं माना जाएगा।

हालाँकि, क्लैंग जानबूझकर इस सुविधा को डिफ़ॉल्ट रूप से लागू नहीं करने का विकल्प चुनता है। से उनकी स्थिति :

दोष रिपोर्ट का रिज़ॉल्यूशन होने के बावजूद, यह सुविधा सभी भाषा संस्करणों में डिफ़ॉल्ट रूप से अक्षम है, और -frelaxed-template-template-argsक्लैंग 4 में ध्वज के साथ स्पष्ट रूप से सक्षम किया जा सकता है । मानक में बदलाव से टेम्पलेट आंशिक ऑर्डरिंग के लिए संबंधित परिवर्तन का अभाव है, जिसके परिणामस्वरूप उचित और पूर्व-मान्य कोड के लिए अस्पष्टता त्रुटियां हैं। इस मुद्दे के जल्द ही ठीक होने की उम्मीद है।

आप देख सकते हैं कि जब आप उस ध्वज को जोड़ते हैं, तो आपका कोड क्लैंग पर भी अस्पष्ट हो जाता है। आपका उदाहरण एक प्रकार का उचित और पूर्व-मान्य कोड है जो क्लैंग यहाँ से सुरक्षा कर रहा है। इसी तरह का एक उदाहरण मैंने देखा है:

template <class T> struct some_trait;

template <template <class> class C, class A>
struct some_trait<C<A>> { /* ... */ };

template <template <class> class C, class A, class B>
struct some_trait<C<A, B>> { /* ... */ };

some_trait<vector<int>> (बाइनरी संस्करण का उपयोग करके) ठीक हो जाता है, लेकिन अब अस्पष्ट (बाइनरी और बाइनरी संस्करण के बीच) हो जाता है।

MSVC एक ही विकल्प बना सकता है, लेकिन मुझे नहीं पता। मानक के अनुसार सही उत्तर यह है कि कॉल अस्पष्ट है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.