यहाँ हम सहायक प्रकार के काम को आगे:
namespace details {
template<class...Ts>
struct sum_t {};
template<class T>
struct sum_t<T> {
T operator()(T t)const{ return std::forward<T>(t); }
};
template<class T, class...Ts>
struct sum_t<T,Ts...> {
auto operator()(T t, Ts...ts)const
-> decltype(std::declval<T>() + sum_t<Ts...>{}(std::declval<Ts>()...))
{
return std::forward<T>(t) + sum_t<Ts...>{}(std::forward<Ts>(ts)...);
}
};
}
template<class...Ts>
auto sum(Ts...ts)
-> decltype(details::sum_t<Ts...>{}(std::declval<Ts>()...))
// -> std::result_of_t<details::sum_t<Ts...>(Ts...)>
// above line is C++14 and cleaner version of previous line
{
return details::sum_t<Ts...>{}(std::forward<Ts>(ts)...);
}
बुनियादी समस्या यह थी कि एक टेम्पलेट समारोह अपने आप में नहीं देख सकते हैं जब एक में अपनी वापसी प्रकार की गणना -> decltype
खंड।
कुछ काम आसपास हैं। उपर्युक्त काम करना चाहिए, क्योंकि एक टेम्पलेट वर्ग अपने शरीर में आंशिक विशेषज्ञता के अन्य विशेषज्ञताओं को देख सकता है। एक अन्य दृष्टिकोण कोएनिग लुकअप (एडीएल) का उपयोग करना होगा ताकि तत्काल बिंदु तक इसकी रिकर्सिव कॉल की खोज को स्थगित कर दिया जा सके, जहां यह स्वयं पा सकता है। मुझे लगता है कि दूसरा दृष्टिकोण अधिक भ्रमित है।
यदि मैं उत्पादन के लिए अपना खुद का sum
लिखना चाहता था, तो मैं इसे वैकल्पिक रूप से उस प्रकार को लेता हूं जिसे मैं वापस लौटने की उम्मीद करता हूं, और यदि ऐसा होता है तो यह शून्य लंबाई योग (डिफ़ॉल्ट उदाहरण बनाकर) स्वीकार करेगा, लेकिन नहीं यदि मैं 1 या अधिक तर्क पास करता हूं तो यह आवश्यक है कि प्रकार डिफॉल्ट कन्स्ट्रबल हो। लेकिन मुझे पसंद है सामान्य कोड ओवर-इंजीनियर:
template<class R0=void,class...Ts,class R=std::conditional_t<
!std::is_same<R0,void>{},
R0,
std::result_of_t<details::sum_t<Ts...>(Ts...)>
>>
R sum(Ts...ts)
{
return details::sum_t<R, Ts...>{}(std::forward<Ts>(ts)...);
}
जहाँ मैं sum_t
संशोधित पहले पैरामीटर के रूप वापसी प्रकार लेने के लिए:
namespace details {
template<class R,class...Ts>
struct sum_t {
R operator()()const{ return {}; }
};
template<class R, class T>
struct sum_t<R, T> {
using R0 = std::conditional_t<!std::is_same<R,void>{},R,T>;
R0 operator()(T t)const{ return std::forward<T>(t); }
};
template<class R, class T, class...Ts>
struct sum_t<R, T,Ts...> {
using R0 = std::conditional_t<
!std::is_same<R,void>{},
R,
decltype(std::declval<T>() + sum_t<void,Ts...>{}(std::declval<Ts>()...))
>;
R0 operator()(T t, Ts...ts)const
{
return std::forward<T>(t) + sum_t<void,Ts...>{}(std::forward<Ts>(ts)...);
}
};
}
मुझे "लिखने के लिए इस योग करना सक्षम होना चाहते हैं बनाता है , लेकिन प्रत्येक उप-योग को R
पर जारी रखने से पहले "या somesuch।
सी ++ 1z में, आप इसके बजाय एक फ़ोल्ड-एक्सप्रेशन का उपयोग करना चाहेंगे। R
सेट करने में सक्षम होने के नाते अभी भी उपयोगी है, जैसे कि आप एक अभिव्यक्ति टेम्पलेट जोड़ रहे हैं, यह केवल वर्तमान स्कोप के अंत तक अभिव्यक्ति टेम्पलेट के रूप में मान्य हो सकता है।
सी ++ 14 में इस समस्या को ठीक करने के लिए, आपको R
वापसी मान के साथ निरंतरता उत्तीर्ण शैली का उपयोग करना पड़ सकता है।
हम तो खेल में वापसी प्रकार कटौती गुना
Matrix m = sum(many_matrices...);
(उदाहरण के लिए) Eigen में काम करने के लिए अनुमति देने के लिए कर सकता है।
जब आप पहली बार जेनेरिक कोड लिखना शुरू करते हैं, तो आपको खुद से पूछना होगा "खरगोश छेद कितना गहराई से जाना है?"
मैंने आपके प्रश्न को अधिक न्यूनतम होने के लिए संपादित किया, और आपकी टिप्पणी से मेल खाता है। मैं भी कीवर्ड के साथ गड़बड़ कर रहा हूं (यह किसी और को एक ही समस्या खोजने में मदद कर सकता है) – Yakk
ठीक है @ यक, धन्यवाद। – LunaticSoul
संबंधित: http://stackoverflow.com/questions/29995642/create-n-dimensional-vector-with-given-sizes/30002714#30002714 – Barry