c++ সি++ স্ট্যান্ডার্ড কি গ্যারান্টি দেয় যে কোনও এসোসিয়েটিভ পাত্রে একটি ব্যর্থ সন্নিবেশটি মূল্য-রেফারেন্স যুক্তিটি সংশোধন করবে না?




stl language-lawyer (3)

না।

যদিও @NathanOliver উল্লেখ করেছেন যে কোনও উপাদান @NathanOliver হবে না এবং যদি কোনও সমমানের কী না থাকে তবে এটি গ্যারান্টি দেয় না যে আর্গুমেন্টগুলি সংশোধিত হবে না।

প্রকৃতপক্ষে, [map.modififier] নীচে বলে

template <class P>
pair<iterator, bool> insert(P&& x);

return emplace(std::forward<P>(x)). সমতুল্য return emplace(std::forward<P>(x)).

যেখানে emplace কিছু বৈধ তবে অনির্ধারিত অবস্থায় x রেখে অন্য কোনও P নির্মাণের জন্য যুক্তিগুলি পুরোপুরি এগিয়ে নিতে পারে।

এখানে একটি উদাহরণ যা প্রমাণ করেও (প্রমাণিত হয় না) যে std::map (একটি সহযোগী ধারক) দিয়ে একটি মান কিছুটা ঘুরে যায়:

#include <iostream>
#include <utility>
#include <string>
#include <map>

struct my_class
{
    my_class() = default;
    my_class(my_class&& other)
    {
        std::cout << "move constructing my_class\n";
        val = other.val;
    }
    my_class(const my_class& other)
    {
        std::cout << "copy constructing my_class\n";
        val = other.val;
    }
    my_class& operator=(const my_class& other)
    {
        std::cout << "copy assigning my_class\n";
        val = other.val;
        return *this;
    }
    my_class& operator=(my_class& other)
    {
        std::cout << "move assigning my_class\n";
        val = other.val;
        return *this;
    }
    bool operator<(const my_class& other) const
    {
        return val < other.val;
    }
    int val = 0;
};

int main()
{
    std::map<my_class, int> my_map;
    my_class a;
    my_map[a] = 1;
    std::pair<my_class, int> b = std::make_pair(my_class{}, 2);
    my_map.insert(std::move(b)); // will print that the move ctor was called
}
  • gcc (২ টি চাল)
  • clang (1 চাল)
#include <set>
#include <string>
#include <cassert>

using namespace std::literals;

int main()
{
    auto coll = std::set{ "hello"s };
    auto s = "hello"s;
    coll.insert(std::move(s));
    assert("hello"s == s); // Always OK?
}

সি ++ স্ট্যান্ডার্ড কি গ্যারান্টি দেয় যে কোনও এসোসিয়েটিভ পাত্রে একটি ব্যর্থ সন্নিবেশটি মূল্য-রেফারেন্স যুক্তিটি সংশোধন করবে না?


(কেবলমাত্র C ++ 17 এর উত্তর)

আমি বিশ্বাস করি যে নাথান অলিভারের (এখন মুছে ফেলা) উত্তর এবং অ্যান্ডি-এর উত্তরগুলির মধ্যে সঠিক উত্তরটি কোথাও।

অ্যান্ডি যেমন উল্লেখ করেছেন, সাধারণভাবে এই ধরনের গ্যারান্টি উপস্থিত থাকতে পারে না : কখনও কখনও সন্নিবেশ সঞ্চালিত হতে পারে কি না তা নির্ধারণের জন্য লাইব্রেরিকে অবশ্যই একটি সরানো নির্মাণ সম্পাদন করতে হবে। এটি emplace ফাংশনের ক্ষেত্রে হবে, যার আচরণটি স্ট্যান্ডার্ড দ্বারা এইভাবে নির্দিষ্ট করা হয়েছে:

প্রভাবসমূহ: value_type std::forward<Args>(args)... দিয়ে নির্মিত একটি value_type অবজেক্ট t সন্নিবেশ করান std::forward<Args>(args)... যদি এবং কেবলমাত্র t এর কী এর সমতুল্য কী সহ ধারকটিতে কোনও উপাদান না থাকে।

আমরা এটিকে এই বলে ব্যাখ্যা করতে পারি যে অবজেক্ট t যেভাবেই নির্ধারিত হয় তা নির্ধারিত হয় এবং সন্নিবেশটি ঘটতে না পারলে তা নিষ্পত্তি করা হয় কারণ যথাক্রমে সেট বা মানচিত্রে মান t বা t.first ইতিমধ্যে বিদ্যমান রয়েছে exists এবং যেহেতু স্ট্যান্ড std::map template <class P> pair<iterator, bool> insert(P&&) পুনরুত্পাদনকারী, বুল template <class P> pair<iterator, bool> insert(P&&) ও অ্যান্ড) নথিটি এমপ্লেসের ক্ষেত্রে নির্দিষ্ট করা হয়েছে, যেমন অ্যান্ডি উল্লেখ করেছেন, এটির একই আচরণ রয়েছে। সের্গেইএ যেমন উল্লেখ করেছে, এই সমস্যাটি এড়াতে try_emplace পদ্ধতিগুলি তৈরি করা হয়েছে।

যাইহোক, ওপি দ্বারা প্রদত্ত নির্দিষ্ট উদাহরণে, সন্নিবেশ করা মানটি ধারকটির মান ধরণের হিসাবে ঠিক একই ধরণের । যেমন insert কলটির আচরণ নাথানঅলিভারের পূর্বে প্রদত্ত সাধারণ প্রয়োজনীয়তা অনুচ্ছেদে নির্দিষ্ট করা হয়েছে:

প্রভাবসমূহ: t সারণীর সমান কী সহ কনটেইনারটিতে কোনও উপাদান না থাকলে কেবলমাত্র সন্নিবেশ করান।

সেক্ষেত্রে সন্নিবেশ ঘটে না এমন ক্ষেত্রে যুক্তি সংশোধন করার জন্য লাইব্রেরির জন্য কোনও লাইসেন্স দেওয়া হয় না। আমি বিশ্বাস করি যে একটি লাইব্রেরি ফাংশন কল করার মানকটি পরিষ্কারভাবে যা অনুমতি দেয় তা ছাড়া কোনও পর্যবেক্ষণযোগ্য পার্শ্ব প্রতিক্রিয়া থাকার কথা নয়। সুতরাং, এই ক্ষেত্রে, t পরিবর্তন করা উচিত হবে না।


সুস্পষ্ট এবং দ্ব্যর্থহীন নম্বর । স্ট্যান্ডার্ডের এই গ্যারান্টি নেই, এবং এ কারণেই try_emplace বিদ্যমান।

টিকা দেখুন:

সন্নিবেশ বা এমপ্লেসের বিপরীতে, সন্নিবেশটি না ঘটলে মূল কার্যনির্বাহী যুক্তিগুলি থেকে এই ফাংশনগুলি সরানো হয় না , যা মানচিত্রগুলি পরিচালনা করতে সহজ করে তোলে যার মানগুলি চলন -কেবল প্রকারের, যেমন std::map<std::string, std::unique_ptr<foo>>try_emplace , try_emplace কী এবং আর্গুমেন্টগুলি ম্যাপেড_ টাইপের সাথে আলাদাভাবে বিবেচনা করে, এম্পলেসের বিপরীতে, যার জন্য একটি value_type (যেটি value_type std::pair ) তৈরি করতে আর্গুমেন্টের প্রয়োজন হয়





pass-by-rvalue-reference