c++ - কনস্ট স্ট্যান্ড:: স্ট্রিং গ্রহণ এবং 0 গ্রহণ করা থেকে ফাংশন আটকাবেন




string std (2)

একটি বিকল্প হ'ল operator[]() এর একটি private ওভারলোড ঘোষণা করা যা একটি অবিচ্ছেদ্য যুক্তি গ্রহণ করে, এবং এটি সংজ্ঞা দেয় না।

এই বিকল্পটি সমস্ত সি ++ স্ট্যান্ডার্ডের সাথে কাজ করবে (1998-এ), void operator[](std::nullptr_t) = delete মতো বিকল্পগুলির তুলনায় void operator[](std::nullptr_t) = delete যা সি ++ 11 থেকে বৈধ।

operator[]() কোনও private সদস্য ohNo[0] আপনার উদাহরণে এটি ohNo[0] ত্রুটি ohNo[0] , যদি না এই অভিব্যক্তিটি কোনও সদস্য ফাংশন বা শ্রেণীর friend দ্বারা ব্যবহৃত হয়।

যদি এই অভিব্যক্তিটি কোনও সদস্য ফাংশন বা শ্রেণীর friend থেকে ব্যবহৃত হয়, কোডটি সংকলন করবে তবে - যেহেতু ফাংশনটি সংজ্ঞায়িত হয়নি - সাধারণত বিল্ডটি ব্যর্থ হবে (যেমন একটি অপরিবর্তিত ফাংশনের কারণে লিঙ্কার ত্রুটি)।

এক হাজার শব্দ মূল্যবান:

#include<string>
#include<iostream>

class SayWhat {
    public:
    SayWhat& operator[](const std::string& s) {
        std::cout<<"here\n"; // To make sure we fail on function entry
        std::cout<<s<<"\n";
        return *this;
    }
};

int main() {
    SayWhat ohNo;
    // ohNo[1]; // Does not compile. Logic prevails.
    ohNo[0]; // you didn't! this compiles.
    return 0;
}

একটি স্ট্রিং গ্রহণ করে বন্ধনী অপারেটরের কাছে 0 নম্বরটি পাস করার সময় সংকলকটি অভিযোগ করছে না। পরিবর্তে, এই পদ্ধতিতে প্রবেশের আগে এই সংকলন এবং ব্যর্থ হয়:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid

রেফারেন্সের জন্য:

> g++ -std=c++17 -O3 -Wall -Werror -pedantic test.cpp -o test && ./test
> g++ --version
gcc version 7.3.1 20180303 (Red Hat 7.3.1-5) (GCC)

আমার ধারণা

সংকলক সুস্পষ্টভাবে পদ্ধতিতে প্রবেশের জন্য std::string(0) কনস্ট্রাক্টর ব্যবহার করছে, যা কোনও কারণ ছাড়াই একই সমস্যা (উপরের ত্রুটির গুগল) দেয়।

প্রশ্ন

ক্লাস সাইডে এটি ঠিক করার কোনও উপায় আছে, তাই API ব্যবহারকারী এটি অনুভব করে না এবং সংকলনের সময় ত্রুটিটি সনাক্ত করা যায়?

এটি একটি ওভারলোড যুক্ত করা হচ্ছে

void operator[](size_t t) {
    throw std::runtime_error("don't");
}

একটি ভাল সমাধান নয়।


std::string(0) বৈধ হওয়ার কারণ 0 নাল পয়েন্টার ধ্রুবক হওয়ার কারণে। সুতরাং এটি একটি পয়েন্টার গ্রহণকারী কনস্ট্রাক্টরের সাথে মেলে। তারপরে এটি পূর্ব শর্তের অনেক আগে চলে যে কেউ std::string নাল পয়েন্টারটি পাস করতে পারে না। কেবল আক্ষরিক 0 একটি নাল পয়েন্টার ধ্রুবক হিসাবে ব্যাখ্যা করা হবে, যদি এটি কোনও int একটি রান টাইম মান হত তবে আপনার এই সমস্যা হবে না (কারণ তারপরে ওভারলোড রেজোলিউশনটি কোনও int রূপান্তর অনুসন্ধান করবে)। আক্ষরিক 1 সমস্যাও নয়, কারণ 1 নাল পয়েন্টার ধ্রুবক নয়।

যেহেতু এটি একটি সংকলন সময় সমস্যা (আক্ষরিক অবৈধ মান) আপনি এটি সংকলন সময়ে ধরতে পারেন। এই ফর্মটির একটি ওভারলোড যুক্ত করুন:

void operator[](std::nullptr_t) = delete;

std::nullptr_t ধরণ। এবং এটি যে কোনও নাল পয়েন্টার ধ্রুবকটির সাথে 0ULL , তা 0 , 0 0ULL বা nullptr । এবং যেহেতু ফাংশনটি মুছে ফেলা হয়েছে, এটি ওভারলোড রেজোলিউশনের সময় একটি সংকলন সময় ত্রুটির সৃষ্টি করবে।







implicit-conversion