पैरामीटर पैक के समूहबद्ध या युग्मित गुना कैसे बनाएं?


14
template<class Msg, class... Args>
std::wstring descf(Msg, Args&&... args) {
    std::wostringstream woss;

    owss << Msg << ". " << ... << " " << args << ": '" << args << "' ";//not legal at all

    //or

    owss << Msg << ". " << args[0] << ": '" << args[1] << "'  " << args[2] << ": '" << args[3] << "' "; //... pseudo code, and so on...
}

मुझे पता है कि मैं इसके बजाय जोड़े की सूची या कुछ और का उपयोग कर सकता हूं, लेकिन मैं इस बात में दिलचस्पी रखता हूं कि फ़ंक्शन का सिंटैक्स रखते हुए यह कैसे करें:

const auto formatted = descf(L"message", "arg1", arg1, "arg2", arg2);

जवाबों:


9

आप एक गुना अभिव्यक्ति का उपयोग कर सकते हैं! यह सबसे सुंदर * नहीं है, लेकिन यह सभी गैर-गुना समाधानों की तुलना में कम है:

template<class T, class ... Args>
std::wstring descf(T msg, Args&&... args) {
    std::wostringstream owss;
    owss << msg << ". ";

    std::array<const char*, 2> tokens{": '", "' "};
    int alternate = 0;
    ((owss << args << tokens[alternate], alternate = 1 - alternate), ...);

    return owss.str();
}

नमूना आउटपुट के साथ डेमो: https://godbolt.org/z/Gs8d2x

हम अल्पविराम ऑपरेटर पर एक गुना करते हैं, जहां प्रत्येक ऑपरेंड एक argsऔर एक वैकल्पिक टोकन का उत्पादन होता है , साथ ही टोकन इंडेक्स को स्विच करता है (बाद वाले दो अन्य कॉमा ऑपरेटर के साथ संयुक्त होते हैं)।

* गुना अभिव्यक्तियों (और अल्पविराम ऑपरेटर) से परिचित पाठक में, यह शायद "सबसे अच्छा" कोड है, लेकिन बाकी सभी के लिए यह पूरी तरह से अस्पष्ट है, इसलिए अपने स्वयं के निर्णय का उपयोग करें कि क्या आप इसे अपने कोड आधार पर भड़काना चाहते हैं।


मुझे लगता है कि यह एक बूल (यदि केवल जोड़ीदार isneeded) अला के साथ काम कर सकता है। : बी ^ = सच; और फिर शायद टेनरी ऑपरेटर (b? ":" ",": "" ")
darune

1
@darune ज़रूर, विकल्प को व्यक्त करने के अन्य तरीके हैं। मैंने आउटपुट / वैकल्पिक तर्क को वास्तविक टोकन मूल्यों से अलग करने का फैसला किया, जो कि सरणी अच्छी तरह से पूरा करता है। मैं से अंतर्निहित रूपांतरण नापसंद boolकरने के लिए intजब का अनुक्रमण तो मैं एक वास्तविक साथ चला गया intराज्य टॉगल करने के लिए। और पूर्व- बनाम पोस्टफ़िक्स ++अतिरिक्त मानसिक चक्रों को सत्यापित करने के लिए लेता है (मेरे लिए कम से कम), जबकि पृथक 1 - वास्तव में गलत नहीं हो सकता। संक्षेप में, मैंने इसे यथासंभव पठनीय रखने की कोशिश की, लेकिन यह निश्चित रूप से व्यक्तिगत स्वाद (या लागू स्टाइल गाइड) तक है। max66 ने इसे और अधिक संघनित किया।
मैक्स लैंगहॉफ

std::arrayएक मूल सरणी के बजाय का उपयोग करना एक व्यर्थ जटिलता लगता है।
डिडुप्लिकेटर 15

@ डेड्यूप्लिकेटर मैं दृढ़ता से असहमत हूं, क्योंकि मुझे std::array<const char*, 2>असीम रूप से अधिक पठनीय लगता है const char**। लेकिन फिर से, यह कुछ बहुत अस्पष्ट वाक्यविन्यास के आसपास पठनीयता पर मेरा सबसे अच्छा शॉट है, आप इसे अपने स्वयं के कोड में पसंद करते हैं। मैं जो कुछ भी कर सकता हूं, वह आपको वह डेटा बिंदु दे सकता है, जिसे मैं पठनीय मानता हूं।
मैक्स लैंगहॉफ

9

यह सहायक कार्यों के एक जोड़े के साथ आसान है जो निम्नलिखित पैटर्न का पालन करते हैं।

void helper() {}

template <class T1, class T2, class ... T>
void helper(T1 t1, T2 t2, T ... t)
{
     do_single_pair(t1, t2);
     helper(t...);
}

यह एक गुना अभिव्यक्ति नहीं है लेकिन शुद्ध परिणाम समान है।


क्या टेम्प्लेट पुनरावृत्ति की गहराई गुना अभिव्यक्ति के साथ भिन्न होगी? या यह वही होगा
darune

1
@darune फोल्ड एक्सप्रेशंस के साथ कोई अंतर्निहित रिक्रिएशन नहीं है ... फोल्ड एक्सप्रेशंस केवल औपचारिक रूप से कुछ एक्सप्रेशन (वेरिएडिक टेम्पलेट के उस विशिष्ट इंस्टेंटेशन में) का विस्तार करते हैं।
मैक्स लैंगहॉफ

6

मुझे लगता है कि आप एक सूचकांक और एक टर्नरी ऑपरेटर के साथ कोशिश कर सकते हैं।

कुछ इस प्रकार है

template <typename ... Args>
std::wstring descf (std::wstring const & Msg, Args && ... args)
 {
   std::wostringstream woss;

   int i = 0;

   ((woss << Msg << ". "), ... ,(woss << args << (++i & 1 ? ": '" : "' ")));

   return woss.str();
 }

@MaxLanghof इसमें अधिक विभाजकों के लिए आसान विस्तार का लाभ (?) है।
डिडुप्लिकेटर

@Deduplicator मुझे समझ नहीं आ रहा है कि आप क्या जिक्र कर रहे हैं? क्या तुम समझा सकते हो?
मैक्स लैंगहॉफ

@ डेड्यूप्लिकेटर - मेरे लिए यह स्पष्ट नहीं है कि "अधिक विभाजकों के विस्तार" के साथ आपका क्या मतलब है ... वैसे भी ... यह समाधान स्वीकार किए गए के समान है; मुझे नहीं लगता कि यह कमोबेश एक्स्टेंसिबल है। मुझे लगता है कि थोड़ा (थोड़ा! शायद कंपाइलर एक ही तरीके से अनुकूलन करता है) लाइटर क्योंकि एक std::array(कि, वैसे भी, एक हल्का वर्ग है) के उपयोग से बचें , लेकिन (इसलिए मुझे लगता है कि बेहतर जवाब पसंद है) कम पठनीय है।
अधिकतम ६६

2

निम्नलिखित कोड को चाल करना चाहिए। पैरामीटर पैक को एक इनिशलाइज़र सूची में विस्तारित किया जाता है।

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

template <typename...Args>
std::string descf(std::string msg, Args &&... args)
{
   auto argumentsVector = std::vector<std::string>{args...};

   std::stringstream ss;
   ss << msg << ". ";

   for (auto i = std::size_t{0}; i < argumentsVector.size() - 1; ++i)
      ss << argumentsVector[i] << ": '" << argumentsVector[i+1] << "' ";

   auto result = ss.str();
   if (!argumentsVector.empty())
       result.pop_back();
   return result;
}

int main()
{
   std::cout << descf("message", "arg1", "1", "arg2", "2") << std::endl;
}

यह सभी argsको एस के लिए परिवर्तनीय होना चाहिए std::string
अखरोट

@wnut, यह सही है। यदि यह एक आवश्यकता नहीं हो सकती है, तो आपको अभिव्यक्ति / पुनरावृत्ति को परिणामित करना होगा
मटियास डे चारलेरॉय

1

के साथ std::index_sequence:

template <class Msg, class... Pairs>
std::wstring descf_pair(const Msg& msg, const Pairs&... pairs)
{
    std::wstringstream woss;

    woss << msg << ". ";
    auto sep = L"";
    ((woss << sep << std::get<0>(pairs) << L": '"
                  << std::get<1>(pairs) << L"'", sep = L"  "), ...);
    return woss.str();
}

template <class Msg, std::size_t... Is, class Tuple>
decltype(auto) descf_impl(const Msg& msg, std::index_sequence<Is...>, Tuple&& t)
{
    return descf_pair(msg, std::tie(std::get<2 * Is>(t), std::get<2 * Is + 1>(t))...);
}

template <class Msg, typename ... Ts>
std::wstring descf(const Msg& msg, const Ts&... ts)
{
    static_assert(sizeof...(Ts) % 2 == 0);

    return descf_impl(msg,
                      std::make_index_sequence<sizeof...(Ts) / 2>(),
                      std::tie(ts...));
}

डेमो

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