2015-10-28 12 views
9

, variadic टेम्पलेट्स, कक्षाएं, कार्यों और lambdas के साथ खेलने के दौरान (from here) मैंने पाया कि निम्न कोड clang++ जबकि नहींg++ के साथ चल साथ चल रहा है:variadic का उपयोग कर टेम्पलेट lambdas: जी के साथ त्रुटि ++ लेकिन बजना ++ के साथ चल रहा

#include <iostream> 
#include <string> 
using namespace std; 
template <class... F> 
struct overload_set : F... 
{ 
    overload_set(F... f) : F(f)... {} 
}; 
template <class... F> 
auto overload(F... f) 
{ 
    return overload_set<F...>(f...); 
} 
int main() 
{ 
    auto func = overload (
     [](int &val) { val *= 2; }, 
     [](string &arg) { arg += arg; }, 
     [](char &c) { c = 'x'; } 
     ); 
    int val = 10; 
    string str = "stackoverflow"; 
    char ch = 's'; 
    cout << val << " : " << str << " : " << ch << endl; 
    func(val); 
    func(str); 
    func(ch); 
    cout << val << " : " << str << " : " << ch << endl; 
    return 0; 
} 
clang लिए

: coliru

g++ के लिए: coliru

g++operator()func(val), func(str) और func(c) के लिए संदिग्ध operator() दे रहा है। मुझे लगता है कि operator() संदिग्ध नहीं होना चाहिए, क्योंकि प्रत्येक के पास अलग-अलग तर्क हैं।

g++ के साथ समस्या क्या है?

+1

@Niall: यह वास्तव में भेड़ के बच्चे या यहां तक ​​कि विविध टेम्पलेट्स के बारे में नहीं है; बेस 'बी 1', 'बी 2' से प्राप्त सरलतम' स्ट्रक्चर 'को भी दिया गया है ... अलग-अलग' ऑपरेटर() (एक्स एंड) 'कार्यों के साथ, जी ++ को बी 1 :: ऑपरेटर() का उपयोग करने की आवश्यकता है; बी 2 :: ऑपरेटर(); का उपयोग करके; (देखें [यहां] (http://coliru.stacked-crooked.com/a/8bc933418b5ff82f))। –

+1

@ टोनीडी। मुझे लगता है कि यह एक क्लैंग बग है - कुछ परीक्षण इंगित करते हैं कि यहां क्लास ऑपरेटर को कैसे हल करता है, यह आधार वर्गों से कैसे काम करता है, यह बताता है कि यह कैसे कॉल ऑपरेटर को हल करता है। – Niall

+0

@Niall gotcha, clang 'x.operator()()' से अलग 'x() 'को हल करता है। –

उत्तर

3

यह लैम्बडा, वैरैडिक टेम्पलेट्स, ऑपरेटरों या किसी भी उन्नत सी ++ 1 {xy} सामान के साथ बहुत कम नहीं है। के आसान बनाने में करते हैं:

struct foo 
{ 
    void func(int&){} 
}; 
struct bar 
{ 
    void func(char&){} 
}; 

struct test : foo, bar {}; 

int main() 
{ 
    test t; 
    int i = 1; 
    char c = 'a'; 
    t.func(i); 
    t.func(c); 
} 

यह या तो g++ या clang++ में संकलित करने के लिए विफल रहता है। जो भी अच्छी बात है, क्योंकि इस तरह भाषा को काम करने के लिए निर्दिष्ट किया गया है।

अगर हम बदलने funcoperator() को, g++ कार्यक्रम को अस्वीकार करने के लिए जारी है लेकिन clang++ या तो स्वीकार करता है या यह को खारिज कर दिया, कैसे ऑपरेटर कहा जाता है पर निर्भर करता है:

t.operator()(c); // rejected 
t(c);   // accepted 

जो मेरे लिए एक बजना बग की तरह दिखता है।

क्रम संकलन ऊपर कोड बनाने के लिए, एक बहुत छोटे से बदलाव की आवश्यकता है:

struct test : foo, bar { 
    using foo::func; 
    using bar::func; 
}; 

अब मैं पता नहीं निर्देशों का उपयोग में पैक विस्तार काम करने के लिए कैसे, या यह वास्तव में संभव है अगर की है।

template <class... F> struct overload_set; 

template <> struct overload_set<> {}; 

template <class F> struct overload_set<F> : F { 
    using F::operator(); 
    overload_set(F f) : F(f) {} 
}; 

template <class F, class... Fs> 
struct overload_set<F, Fs...> : F, overload_set<Fs...> 
{ 
    overload_set(F f, Fs... fs) : F(f), overload_set<Fs...>(fs...) {} 
    using F::operator(); 
    using overload_set<Fs...>::operator(); 
}; 
इस के साथ

बदलने अपने कोड g++ और clang++ दोनों के साथ संकलित: लेकिन वहाँ एक समाधान है।

+2

ओपी के लिंक किए गए ब्लॉग पोस्ट से एक लिंक है जो इस कामकाज को काफी अधिक है। ब्लॉग इसे "औद्योगिक-शक्ति संस्करण" के रूप में उल्लेख करता है, [यहां लिंक] (https://github.com/picanumber/CODEine/blob/master/lambda_utils.h) – Niall

+0

@Niall औद्योगिक संस्करण वह है जो मेरे पास है दूसरों के बीच याक ने देखा (बेस टेम्पलेट पर विविधताएं हैं, विशेषज्ञता की संख्या और सही अग्रेषण का उपयोग) –

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