2015-10-29 6 views
5

मैं एक ऐसा फ़ंक्शन लिखने की कोशिश कर रहा हूं जो std::tuple के रूप में एक भिन्न तर्क पैक का सबसेट देता है। फ़ंक्शन में आदर्श रूप से कोई रनटाइम ओवरहेड नहीं होना चाहिए (कोई अनावश्यक प्रतियां नहीं), और इसे उपयोगकर्ताओं को lvalue संदर्भों तक पहुंचने और उन्हें संशोधित करने की अनुमति देनी चाहिए।rvaluness को हटाएं, lvalue संदर्भ रखें (मानक प्रकार विशेषता उपलब्ध है?)

मूल्य प्रकार, lvalue संदर्भ और const lvalue संदर्भ बनाए रखा जाना चाहिए। अस्थायी संदर्भ (अस्थायी संदर्भ) से बचने के लिए अस्थायी (rvalue संदर्भ), मूल्य परिवर्तित करने के लिए "रूपांतरित" होना चाहिए।

वांछित परिणामों का उदाहरण:

int lr = 5; 
const int& clr = lr; 

auto t = make_subpack_tuple(lr, clr, 5); 

static_assert(is_same 
< 
    decltype(t), 
    std::tuple<int&, const int&, int> 
>{}, ""); 

// Ok, modifies lr: 
std::get<0>(t) = 10; 

// Compile-time error, intended: 
// std::get<1>(t) = 20; 

// Ok, 5 was moved into the tuple: 
std::get<2>(t) = 30; 

उदाहरण अधूरा कार्यान्वयन:

template<typename... Ts> 
auto make_subpack_tuple(Ts&&... xs) 
{ 
    return std::tuple 
    < 
     some_type_trait<decltype(xs)>... 
    > 
    (
     std::forward<decltype(xs)>(xs)... 
    ); 
} 

कि मैं क्या मतलब है करने के लिए कोशिश कर रहा हूँ करता है?

क्या कोई मानक प्रकार-विशेषता है जिसका उपयोग some_type_trait के स्थान पर किया जा सकता है? या मुझे अपने स्वयं के समाधान को लागू करना चाहिए?

+0

मैं बस उत्सुक हूँ। आप ऐसा करने में रुचि क्यों रखते हैं? आप क्या समस्या हल कर रहे हैं? –

+0

मैं एक 'static_for' के समान कुछ कार्यान्वित कर रहा हूं जो उपयोगकर्ता द्वारा निर्दिष्ट धैर्य के साथ विषम मूल्यों पर कॉल करने योग्य ऑब्जेक्ट निष्पादित करता है, और उपयोगकर्ता को संकलन समय पर वर्तमान पुनरावृत्ति संख्या पुनर्प्राप्त करने और ब्रेक/जारी रखने की अनुमति देता है * (प्रारंभ से बाहर निकलें) * 'static_if' का उपयोग कर संकलन समय पर। कार्यान्वयन के एक हिस्से को भिन्न आंतरिक तर्क पैक के पहले 'एन' तर्कों को किसी अन्य आंतरिक कार्य में गुजरने की आवश्यकता होती है, और मैं कुछ भिन्न तर्क तर्क मैनिपुलेशन कार्यों को परिभाषित करके सामान्यीकृत करने की कोशिश कर रहा था। 'Nth ' के अलावा, मुझे 'subpack ' की आवश्यकता है कि उस व्यवहार को पूरी तरह से सामान्यीकृत करने के लिए –

+0

उपयोगकर्ता द्वारा निर्दिष्ट धर्मार्थता से मेरा मतलब है कि 'static_for'' N' के समूहों में विषम मूल्यों पर पुनरावृत्त करता है (जहां 'एन' है उपयोगकर्ता द्वारा निर्दिष्ट टेम्पलेट पैरामीटर)। कॉल करने योग्य ऑब्जेक्ट जो 'static_for' के शरीर का प्रतिनिधित्व करता है, उसी धर्मार्थ के साथ 'ऑपरेटर()' होना चाहिए। साथ ही, मैं इसे ओपन-सोर्स सी ++ 14 सामान्य प्रयोजन लाइब्रेरी ([vrm_core] (https://github.com/SuperV1234/vrm_core)) के लिए कर रहा हूं, मजेदार और सीखने के उद्देश्यों के लिए लिखा गया है। उम्मीद है कि आपके प्रश्न का उत्तर दें :) –

उत्तर

7

आप के लिए समाधान हो जाएगा

template<typename... Ts> 
auto make_subpack_tuple(Ts&&... xs) 
{ 
    return std::tuple<Ts...>(std::forward<Ts>(xs)...); 
} 

template argument deduction rules के अनुसार, पैरामीटर पैक Ts... केवल सीवी योग्य प्रकार और lvalues ​​शामिल होंगे। this question में जानकारी भी उपयोगी हो सकती है।

1

मैं इस बात में झुकना चाहता हूं कि मैं Nick Athanasios's foldable Op<operation> के एक कुशल संस्करण को कार्यान्वित करते हुए, वास्तव में एक समस्या में भाग गया ("मुझे लगता है कि मुझे रैल्यू संदर्भों को क्षीण करने और लैव्यू संदर्भों को छूटा जाना चाहिए")। (कि सत्यापित करने के लिए एक बिट के लिए puzzling, और फिर एक ऐसा सवाल पूछने के लिए शुरू करने, और इस मौजूदा प्रश्न/उत्तर खोजने और mystery_trait_t की मेरी कार्यान्वयन के लिए एक static_assert जोड़ने के बाद

template<class Pack, class Op> 
struct Foldable 
{ 
    mystery_trait_t<Pack> value; 
    const Op& op; 

    template<class RhsPack> 
    auto operator*(const Foldable<RhsPack, Op>& rhs) const { 
     return op(static_cast<std::decay_t<Pack>>(
      (op.f)(std::move(value), std::move(rhs.value)) 
     )); 
    } 

    operator mystery_trait_t<Pack>() && { 
     return std::move(value); 
    } 
}; 

template<class Pack> 
auto NamedOperator::operator()(Pack&& value) const { 
    return Foldable<Pack, NamedOperator>(std::forward<Pack>(value), *this); 
} 

और: मैं इस गड़बड़ था यह वास्तव में एक rvalue संदर्भ प्रकार के साथ लागू नहीं किया गया था!) ​​यह है कि सभी मैं वास्तव में जरूरत निकला

template<class Pack, class Op> 
struct Foldable 
{ 
    Pack value; 
    const Op& op; 

    template<class RhsPack> 
    auto operator*(const Foldable<RhsPack, Op>& rhs) const { 
     return op(
      (op.f)(std::move(value), std::move(rhs.value)) 
     ); 
    } 

    operator Pack() && { 
     return std::move(value); 
    } 
}; 

(See my whole code on Wandbox.)

यह मेरा "जवाब" कोई नई जानकारी योगदान नहीं करता था, लेकिन मैंने सोचा था कि यह साझा करने के लिए उपयोगी होगा, क्योंकि यह सिर्फ यह दिखाने के लिए चला जाता है कि भले ही आपको लगता है कि आप टेम्पलेट मेटाप्रोग्रामिंग में गहरे हैं और सुनिश्चित हैं आपको इस "सशर्त क्षय" व्यवहार की आवश्यकता है ... आपको वास्तव में इसकी आवश्यकता नहीं है !

एक कोरोलरी सामान्य नियम हो सकता है कि लेखन any_template<T&&> हमेशा एक कोड गंध है। विटोरियो के मूल प्रश्न में उन्होंने प्रभावी ढंग से कि दो बार, किया था, हालांकि दोनों बार यह decltype वाक्य रचना से छिपा हुआ था:

some_type_trait<decltype(xs)>... // should have been `Ts...` 
std::forward<decltype(xs)>(xs)... // could equally well be `std::forward<Ts>(xs)...` 
संबंधित मुद्दे