অস্পষ্ট ওভারলোড টেম্পলেটগুলি


16

আমার নীচের টেম্প্লেটেড কোড রয়েছে

#include <vector>
#include <array>
#include <iostream>

template<typename T1>
void foo(std::vector<T1> bar) {
    std::cout << "GENERIC" << std::endl;
}

template<typename T1>
void foo(std::vector<std::vector<T1>> bar) {
    std::cout << "SPECIFIC (vector)" << std::endl;
}

template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

int main() {
    std::vector<std::vector<int>> a(2, std::vector<int> { 1, 2, 3});
    std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});

    foo(a);
    foo(b);
}

যা উত্পাদন করে

SPECIFIC (vector)
GENERIC

আমি ভাবছি যে কেন ভেক্টর অফ-ভেক্টর সংস্করণটি নির্দিষ্ট টেম্পলেটটির সাথে ডাকা হয়, তবে ভেক্টর অফ অ্যারে সংস্করণটিকে জেনেরিকের সাথে ডাকা হয়?


2
এফওয়াইআই: আপনি একই বিষয়টির সাথে vectorতাদের সকলের উপরের অংশটি সরিয়ে সরল করতে পারেন । এখানে দেখুন
ক্রিসএমএম

পছন্দ করেছেন এই উদাহরণটি আমার উত্পাদন কোড থেকে সংশ্লেষিত হয়েছিল, যেখানে নেস্টেড কাঠামোটি প্রয়োজনীয় necessary
জেসার

5
এমএসভিসি ভেক্টর অফ-অ্যারে সংস্করণটি কল করেছে: Godbolt.org/z/7Gfeb0
আরটি

উত্তর:


8
template<typename T1, size_t SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

এর std::size_tপরিবর্তে আপনার ব্যবহার করা উচিত intএখানে চালাও

সম্পাদনা করুন: আসলে, আপনার মন্তব্য এবং কোড সম্পর্কে আমার স্বীকৃতি আমাকে বিষয়টিতে খনন করতে পরিচালিত করেছিল। প্রথম নজরে, একটি স্ট্যান্ডার্ড বিকাশকারী (আমার মতো) সংকলককে রূপান্তর intকরার প্রত্যাশা করে std::size_t(কারণ তারা উভয়ই অবিচ্ছেদ্য ধরণের এবং অন্তর্নিহিত রূপান্তরকারী খুব তুচ্ছ) এবং void foo(std::vector<std::array<T1, SIZE>> bar)সেরা বিশেষজ্ঞ হিসাবে নির্বাচন করুন । সুতরাং টেমপ্লেট যুক্তি ছাড়ের পৃষ্ঠাটি পড়ার সময় আমি এটি খুঁজে পেয়েছি:

যদি পরামিতি তালিকায় একটি নন-টাইপ টেম্পলেট প্যারামিটার ব্যবহার করা হয়, এবং সংশ্লিষ্ট টেম্পলেট যুক্তিটি অনুমিত হয়, তবে অনুমিত টেম্পলেট আর্গুমেন্টের ধরণ (যার সাথে সংযুক্ত টেম্পলেট প্যারামিটার তালিকায় নির্দিষ্ট করা হয়েছে, যার অর্থ রেফারেন্সগুলি সংরক্ষণ করা আছে) অবশ্যই এর ধরণের সাথে মেলে সিভি-কোয়ালিফায়ার বাদ দেওয়া বাদে এবং অ-প্রকারের টেম্পলেট প্যারামিটারটি হুবহু, আর যেখানে টেমপ্লেট আর্গুমেন্টকে অ্যারে বাউন্ড থেকে বাদ দেওয়া হয় except সেই ক্ষেত্রে কোনও অখণ্ড প্রকার অনুমোদিত, এমনকি বুল যদিও এটি সর্বদা সত্য হয়ে যায়:

অবশ্যই সর্বদা হিসাবে, এর অর্থ বোঝার জন্য আপনাকে অবশ্যই একবারের চেয়ে আরও কয়েকবার পড়তে হবে :)

সুতরাং একটি আকর্ষণীয় ফলাফল প্রকাশিত হয়।

ইতিমধ্যে আমাদের কাঙ্ক্ষিত বিশেষত্ব নির্বাচন করা হয়নি তবে কম্পাইলারটি নির্বাচন করতে বাধ্য করা হলে এটি ত্রুটি হবে।

template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

int main() {
    std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});

    foo(b); // P = std::vector<std::array<int,(int)SIZE>
            // A = std::vector<std::array<int,(unsigned_long)SIZE>>
            // error: deduced non-type template argument does not have the same
            // type as its corresponding template argument */
}

রান কোড

আর একটি আকর্ষণীয় বিষয় হ'ল:

যদি নন-টাইপ টেম্পলেট আর্গুমেন্টটি অনুমিত না করা হয়, তবে কোনও বাধা থাকত না যা যুক্তি এবং টেম্পলেট ধরণেরগুলিকে একই হতে বাধ্য করে।

#include <vector>
#include <array>
#include <iostream>

template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

int main() {
    std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});

    foo<int,3>(b);
}

রান কোড


@ জাসার কারণ অ্যারের দ্বিতীয় টেমপ্লেট যুক্তিটি টাইপের size_t...
জিন-ব্যাপটিস্ট ইউনুস

2
আর 2 আরটি-র মন্তব্য বিবেচনা করে, সংকলক নির্দিষ্ট পার্থক্য হিসাবে উপস্থিত হবে।
জেসার

8

আমি মনে করি এটি কেবল এক লাইনের কারণে[temp.deduct.call]/4

সাধারণভাবে, ছাড়ের প্রক্রিয়াটি টেমপ্লেট আর্গুমেন্টের মানগুলি সন্ধান করার চেষ্টা করে যা বিয়োগকে A এর মতো করে তুলবে

স্পষ্ট করা Aমানে প্যারামিটার, থেকে[temp.deduct.call]/1

... কলটির সম্পর্কিত আর্গুমেন্টের ধরণের সাথে টেমপ্লেট আর্গুমেন্ট ছাড় uction (এটিকে কল করুন) ...

ইতিমধ্যে চিহ্নিত করা হয়েছে যে, আপনি যে সমস্যাটি দেখছেন সেটি সংশোধন করে পরিবর্তন template<typename T1, int SIZE>করা template<typename T1, size_t SIZE>। যেমনটি বলা হয়েছে [temp.deduct.call]/4, সংকলকটি Aসাদৃশ্যপূর্ণ কোনওটি কমানোর চেষ্টা করছে A। যেহেতু std::arrayএকটিতে টেমপ্লেট আর্গুমেন্ট রয়েছে <class T, size_t N>(থেকে [array.syn]), এটি দ্বিতীয় প্যারামিটারটি আসলে size_t, না int

সুতরাং, টেমপ্লেট ছাড়ের জন্য, আপনার জেনেরিক ফাংশন হুবহু ঠিক এর ধরণের template<typename T1>সাথে মেলে সক্ষম , যেখানে আপনার বিশেষ হিসাবে কোনও নির্দিষ্ট মিল নেই। আমি বিশ্বাস করি এমএসভিসি এর ছাড়ের ক্ষেত্রে ভুল।Atemplate<typename T1, int SIZE>

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