প্যারামিটার প্যাকের গোষ্ঠীযুক্ত বা জোড়াযুক্ত ভাঁজ কীভাবে করবেন?


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এবং বিকল্প টোকেন, এবং টোকেন সূচকটি স্যুইচ করে (দ্বিতীয়টি দুটি অন্য কমা অপারেটরের সাথে মিলিত হয়)।

* ভাঁজ এক্সপ্রেশন (এবং কমা অপারেটর) এর সাথে পরিচিত কোনও পাঠকের কাছে এটি সম্ভবত "সেরা" কোড, তবে অন্য সবার জন্য এটি সম্পূর্ণ জঘন্য, সুতরাং আপনি নিজের কোড ভিত্তিতে এটি চাপিয়ে দিতে চান কিনা তা আপনার নিজের রায় ব্যবহার করুন।


আমার ধারণা, এটি একটি বুলের সাথেও কাজ করতে পারে (যদি কেবল জুটি বেঁধে দেওয়া হয়) আলা। : বি ^ = সত্য; এবং তারপরে সম্ভবত টেনারি অপারেটর (বি? ": '", ":"' ")
ডারুন

1
@ দারুনুন অবশ্যই, বিকল্পটি প্রকাশের অন্যান্য উপায়ও রয়েছে আমি আউটপুট / বিকল্প যুক্তিকে প্রকৃত টোকেন মানগুলি থেকে আলাদা করার সিদ্ধান্ত নিয়েছি, যা অ্যারেটি সুন্দরভাবে সম্পাদন করে। ইনডেক্স boolকরার intসময় আমি অন্তর্নিহিত রূপান্তরকে অপছন্দ করি তাই আমি intরাজ্যে টগল করার জন্য একটি বাস্তবের সাথে গিয়েছিলাম । প্রাক-বনাম পোস্টফিক্সটি ++যাচাই করতে অতিরিক্ত মানসিক চক্র গ্রহণ করে (আমার পক্ষে কমপক্ষে), যদিও 1 - পৃথকটি সত্যই ভুলভাবে পড়া যায় না। সংক্ষেপে, আমি এটিকে যতটা সম্ভব পঠনযোগ্য রাখার চেষ্টা করেছি, তবে এটি অবশ্যই ব্যক্তিগত স্বাদ (বা প্রযোজ্য স্টাইল গাইড) পর্যন্ত। সর্বোচ্চ 66 এটি আরও ঘনীভূত করে।
ম্যাক্স ল্যাংফোফ

std::arrayনেটিভ অ্যারের পরিবর্তে ব্যবহার করা অর্থহীন জটিলতা বলে মনে হয়।
ডিসিপ্লিকেটর

@Deduplicator আমি দৃঢ়ভাবে অসম্মতি, যেমন আমি খুঁজে 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...);
}

এটি কোনও ভাঁজ প্রকাশ নয় তবে নেট ফলাফল একই result


ভাঁজ প্রকাশের চেয়ে টেমপ্লেট পুনরাবৃত্তি গভীরতা কি আলাদা হবে? বা এটি একই হবে
darune

1
@ সদরুনে ভাঁজ প্রকাশের সাথে অন্তর্নিহিত পুনরাবৃত্তি নেই ... ভাঁজ প্রকাশগুলি আনুষ্ঠানিকভাবে কিছু অভিব্যক্তিতে প্রসারিত হয় (বৈকল্পিক টেমপ্লেটের সেই নির্দিষ্ট ইনস্ট্যান্টিশনে)।
ম্যাক্স ল্যাংফোফ

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();
 }

@ ম্যাক্সল্যাংহোফ এটি আরও বিভাজনকারীদের সহজ বর্ধনের সুবিধা (?) Has
ডিসিপ্লিকেটর

@ ডেডুপ্লিকেটর আপনি কী উল্লেখ করছেন তা আমি বুঝতে পারি না? তুমি কি ব্যাখ্যা করতে পারো?
সর্বোচ্চ ল্যাঙ্গোফ

@ উত্সাহক - "আরও বিভাজকগুলিতে এক্সটেনশন" বলতে কী বোঝাতে চেয়েছেন তা আমার কাছে পরিষ্কার নয় ... যাইহোক ... এই সমাধানটি গ্রহণীকৃতটির সাথে খুব মিল; আমি মনে করি না এটি কম-বেশি এক্সটেনসিবল। আমি অনুমান করি যে এটি সামান্য (সামান্য! সম্ভবত একইভাবে সংকলকটি অপ্টিমাইজ করা) হালকা কারণ একটি std::array(যা যাইহোক, একটি হালকা বর্গ) এর ব্যবহার এড়িয়ে চলুন তবে (তাই আমি মনে করি গ্রহণযোগ্য উত্তরটি পছন্দনীয়) কম পাঠযোগ্য।
সর্বোচ্চ 66

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
আখরোট

@ ওয়ালনাট, এটি সঠিক। যদি এটির প্রয়োজন নাও হতে পারে, তবে আপনাকে ভাব / পুনরাবৃত্তি ভাঁজ করতে হবে
Mattias De Charleroy

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...));
}

ডেমো

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.