সমষ্টিগত আরম্ভের জন্য খালি বেস শ্রেণি লুকান


9

নিম্নলিখিত কোড বিবেচনা করুন:

struct A
{
    // No data members
    //...
};

template<typename T, size_t N>
struct B : A
{
    T data[N];
}

এইভাবে আপনাকে বি সূচনা করতে হবে: B<int, 3> b = { {}, {1, 2, 3} }; আমি বেস শ্রেণীর জন্য অপ্রয়োজনীয় খালি avoid avoid এড়াতে চাই। একটি সমাধান Jarod42 দ্বারা প্রস্তাবিত হয় এখানে যদিও, উপাদান ডিফল্ট আরম্ভের সাথে কাজ করে না: B<int, 3> b = {1, 2, 3};জরিমানা কিন্তু B<int, 3> b = {1};নয়: b.data[1]এবং b.data[2]0 সক্রিয়া ডিফল্টভাবে হয় না, এবং কম্পাইলার ত্রুটি দেখা দেয়। নির্মাণ থেকে বেস ক্লাসটি "আড়াল" করার কোনও উপায় আছে (বা সি ++ এর সাথে থাকবে)?


2
কেন কনস্ট্রাক্টর যুক্ত করবেন না template<class... Ts> B(Ts... args) : data{args...} {}?
এভগ

কেন এটি একটি মন্তব্য? মনে হচ্ছে এটি কাজ করছে, হ্যাঁ
ব্যবহারকারী 7769147

এটি এমন একটি সুস্পষ্ট সমাধান যা আমি ভেবেছিলাম এটি ব্যবহার না করার আপনার কোনও কারণ রয়েছে। :)
এভগ

এটি খুব সহজ এক্সডি ছিল। আপনি যদি এটি উত্তর হিসাবে লিখেন তবে আমি এটি গ্রহণ করব
user7769147

উত্তর:


6

সবচেয়ে সহজ সমাধানটি হ'ল ভ্যারিয়েডিক কনস্ট্রাক্টর যুক্ত করা:

struct A { };

template<typename T, std::size_t N>
struct B : A {
    template<class... Ts, typename = std::enable_if_t<
        (std::is_convertible_v<Ts, T> && ...)>>
    B(Ts&&... args) : data{std::forward<Ts>(args)...} {}

    T data[N];
};

void foo() {
    B<int, 3> b1 = {1, 2, 3};
    B<int, 3> b2 = {1};
}

আপনি যদি {...}আরম্ভের তালিকার তুলনায় কিছু কম উপাদান সরবরাহ করেন Nতবে অ্যারেতে থাকা অবশিষ্ট উপাদানগুলি dataমান হিসাবে-আরম্ভ হবে T()


3
আমি কেন এটি সামগ্রিক সূচনা থেকে আলাদা তা সন্ধান করেছি। আপনি যদি বিবেচনা করেন B<Class, 5> b = {Class()}; Classতবে প্রথমে নির্মাণ করা হবে এবং তারপরে সরানো হবে, যখন সামগ্রিক Class
সূচনাটি

@ ব্যবহারকারী 7769147, ভাল পয়েন্ট। আপনি std::tupleআর্গুমেন্ট নিতে পারেন এবং স্থানে বস্তুগুলি তৈরি করতে তাদের ব্যবহার করতে পারেন। তবে বাক্য গঠনটি বরং জটিল হবে।
এভগ

1
আমি এলোমেলোভাবে একটি সমাধান পেয়েছি যা এই সমস্যার সমাধান করে, আমি আপনার উপলব্ধতার জন্য ধন্যবাদ জানার জন্য এটি গ্রহণযোগ্য উত্তর হিসাবে ছেড়ে যাব :)
ব্যবহারকারী 7769147

4

সি ++ ২০ যেহেতু আপনি সামগ্রিক সূচনাতে মনোনীত প্রারম্ভিক ব্যবহার করতে পারেন ।

B<int, 3> b = { .data {1} }; // initialize b.data with {1}, 
                             // b.data[0] is 1, b.data[1] and b.data[2] would be 0

এটি এখনও আমার পক্ষে খুব ভার্জোজ, এটি একটি ন্যূনতম উদাহরণ। আমার অ্যারে
সদস্যটির

4

এখনও কনস্ট্রাক্টর সহ আপনি এমন কিছু করতে পারেন:

template<typename T, size_t N>
struct B : A
{
public:
    constexpr B() : data{} {}

    template <typename ... Ts,
              std::enable_if_t<(sizeof...(Ts) != 0 && sizeof...(Ts) < N)
                               || !std::is_same_v<B, std::decay_t<T>>, int> = 0>
    constexpr B(T&& arg, Ts&&... args) : data{std::forward<T>(arg), std::forward<Ts>(args)...}
    {}

    T data[N];
};

ডেমো

SFINAE মূলত সিউডো কপি নির্মাণকারী এড়ানোর জন্য করা হয় B(B&)

B<std::index_sequence<0, 1>, 42>;-) সমর্থন করার জন্য আপনার অতিরিক্ত প্রাইভেট ট্যাগ লাগবে


তোমার দরকার কেন ((void)Is, T())...? আপনি যদি কেবল এটিকে বাদ দেন? বাকী উপাদানগুলি কি T()ডিফল্টরূপে মান-আরম্ভ হবে না ?
এভগ

1
@ এভিজি: প্রকৃতপক্ষে, সরল। বাকী উপাদানগুলিকে মান আরম্ভের পরিবর্তে কেবল ডিফল্টরূপে আরম্ভ করার জন্য ভয় পেয়েছিল ...
জারোড 42

2

আমি আরেকটি সমাধান খুঁজে পেয়েছি যা (আমি জানি না) কীভাবে পুরোপুরি কাজ করে এবং এভের উত্তরের অধীনে আমরা যে সমস্যাটি নিয়ে আলোচনা করছিলাম তা সমাধান করে

struct A {};

template<typename T, size_t N>
struct B_data
{
    T data[N];
};

template<typename T, size_t N>
struct B : B_data<T, N>, A
{
    // ...
};

আকর্ষণীয় সমাধান। তবে এখন একটি ব্যবহার করতে হবে this->dataবা ভিতরে using B_data::data;প্রবেশ করতে হবে । dataB
Ev
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.