বিভিন্ন বস্তু ব্যবহার করার সময় টেমপ্লেট বিশেষায়নের একাধিক সংজ্ঞা


99

আমি যখন বিভিন্ন অবজেক্ট ফাইলগুলিতে বিশেষায়িত টেম্পলেট ব্যবহার করি, লিঙ্ক করার সময় আমি একটি "বহু সংজ্ঞা" ত্রুটি পাই। আমি যে সমাধান পেয়েছি তার মধ্যে কেবলমাত্র "ইনলাইন" ফাংশনটি ব্যবহার করা জড়িত তবে এটি কেবল কিছুটা কাজের মতো মনে হচ্ছে। "ইনলাইন" কীওয়ার্ডটি ব্যবহার না করে কীভাবে আমি এটি সমাধান করব? যদি তা সম্ভব না হয় তবে কেন?

উদাহরণ কোডটি এখানে:

paulo@aeris:~/teste/cpp/redef$ cat hello.h 
#ifndef TEMPLATE_H
#define TEMPLATE_H

#include <iostream>

template <class T>
class Hello
{
public:
    void print_hello(T var);
};

template <class T>
void Hello<T>::print_hello(T var)
{
    std::cout << "Hello generic function " << var << "\n";
}

template <> //inline
void Hello<int>::print_hello(int var)
{
    std::cout << "Hello specialized function " << var << "\n";
}

#endif

paulo@aeris:~/teste/cpp/redef$ cat other.h 
#include <iostream>

void other_func();

paulo@aeris:~/teste/cpp/redef$ cat other.c 
#include "other.h"

#include "hello.h"

void other_func()
{
    Hello<char> hc;
    Hello<int> hi;

    hc.print_hello('a');
    hi.print_hello(1);
}

paulo@aeris:~/teste/cpp/redef$ cat main.c 
#include "hello.h"

#include "other.h"

int main()
{
    Hello<char> hc;
    Hello<int> hi;

    hc.print_hello('a');
    hi.print_hello(1);

    other_func();

    return 0;
}

paulo@aeris:~/teste/cpp/redef$ cat Makefile
all:
    g++ -c other.c -o other.o -Wall -Wextra
    g++ main.c other.o -o main -Wall -Wextra

শেষ অবধি:

paulo@aeris:~/teste/cpp/redef$ make
g++ -c other.c -o other.o -Wall -Wextra
g++ main.c other.o -o main -Wall -Wextra
other.o: In function `Hello<int>::print_hello(int)':
other.c:(.text+0x0): multiple definition of `Hello<int>::print_hello(int)'
/tmp/cc0dZS9l.o:main.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: ** [all] Erro 1

যদি আমি হ্যালো। H এর অভ্যন্তরে "ইনলাইন" কে অসম্পূর্ণ করে রাখি, কোডটি সংকলন এবং চলবে, তবে এটি কেবল আমার কাছে একরকম "workaround" বলে মনে হচ্ছে: বিশেষায়িত ফাংশনটি যদি বড় হয় এবং বহুবার ব্যবহৃত হয় তবে কী হবে? আমি একটি বড় বাইনারি পাবেন? এটি করার অন্য কোনও উপায় আছে? যদি হ্যাঁ, কিভাবে? তা না হলে কেন?

আমি উত্তরগুলি সন্ধান করার চেষ্টা করেছি, তবে আমার কাছে যা কিছু পেয়েছে তা কোনও ব্যাখ্যা ছাড়াই "ইনলাইন ব্যবহার করুন"।

ধন্যবাদ


7
প্রকৃত বিশেষায়িত বাস্তবায়ন .cpp এর পরিবর্তে তারপরে শিরোনাম ফাইলটিতে দিন
যেকোনোর্ন

উত্তর:


134

স্বজ্ঞাতভাবে, যখন আপনি কোনও কিছুর পুরোপুরি বিশেষজ্ঞ করেন, এটি আর কোনও টেম্পলেট প্যারামিটারের উপর নির্ভর করে না - সুতরাং আপনি যদি বিশেষীকরণটিকে ইনলাইন না করেন তবে আপনাকে এটি .h এর পরিবর্তে একটি .cpp ফাইলে রাখার দরকার নেই বা আপনি লঙ্ঘন করা শেষ করেন ডেভিড হিসাবে একটি সংজ্ঞা নিয়ম। মনে রাখবেন যে আপনি যখন আংশিকভাবে টেম্পলেটগুলিকে বিশেষীকরণ করেন তখন আংশিক বিশেষত্বগুলি এখনও এক বা একাধিক টেম্পলেট প্যারামিটারের উপর নির্ভর করে তাই তারা এখনও একটি .h ফাইলে যায়।


হুমম কীভাবে এটি ওডিআর ভেঙে দেয় সে সম্পর্কে আমি এখনও কিছুটা বিভ্রান্ত। কারণ আপনি কেবল একবার পুরোপুরি বিশেষায়িত টেম্পলেটটি সংজ্ঞায়িত করেন। আপনি বিভিন্ন অবজেক্ট ফাইলগুলিতে একাধিকবার বস্তুটি তৈরি করতে পারেন (যেমন এই ক্ষেত্রে এটি অন্যান্য। এবং মেইন.সি. তে ইনস্ট্যান্টেশনযুক্ত) তবে আসল অবজেক্টটি কেবল একটি ফাইলেই সংজ্ঞায়িত হয় - এই ক্ষেত্রে hello.h
জাস্টিন লিয়াং

4
@ জাস্টিনলিয়াং: শিরোনামটি দুটি পৃথক। সি ফাইলের মধ্যে অন্তর্ভুক্ত রয়েছে - এর একই প্রভাব রয়েছে যেমন আপনি প্রাসঙ্গিক জায়গাগুলিতে অন্তর্ভুক্ত থাকা ফাইলগুলিতে সরাসরি (সম্পূর্ণ বিশেষীকরণ সহ) লিখিত থাকতেন। ওয়ান ডেফিনিশন রুল (দেখুন এন.ইউইকিপিডিয়া.org / উইকি / ওয়ান_ডিফিনিশন_রুল ) বলেছেন (অন্যান্য জিনিসের মধ্যে): "পুরো প্রোগ্রামে কোনও অবজেক্ট বা অন-ইনলাইন ফাংশনটির একাধিক সংজ্ঞা থাকতে পারে না"। এই ক্ষেত্রে, ফাংশন টেমপ্লেটের সম্পূর্ণ বিশেষত্ব সাধারণ ফাংশনের মতোই সংক্ষেপে থাকে, সুতরাং এটি ইনলাইন না হলে এটির একাধিক সংজ্ঞা থাকতে পারে না।
স্টুয়ার্ট গোলোডেটজ

হুঁ, আমি লক্ষ্য করেছি যে যখন আমাদের কোনও পরীক্ষিত বিশেষায়িতকরণ না থাকে তখন এই ত্রুটিটি উপস্থিত হবে না। ধরা যাক আমাদের দুটি ভিন্ন ফাংশন ছিল যা ক্লাসের বাইরে শিরোলেখ ফাইলটিতে সংজ্ঞায়িত হয়েছিল, তারা এখনও ইনলাইন ছাড়াই কাজ করবে? উদাহরণস্বরূপ: পেস্টবিন . com / raw.php ? i=bRaiNC7M । আমি এই ক্লাসটি নিয়েছি এবং এটি দুটি ফাইলে অন্তর্ভুক্ত করেছি। এটির মতোই কি একই প্রভাব থাকবে না যদি আপনি দুটি ফাইলে সরাসরি বিষয়বস্তু লিখেছেন এবং এইভাবে একাধিক সংজ্ঞা ত্রুটি হবে?
জাস্টিন লিয়াং

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

সুতরাং, যদি আমার স্থিতিশীল সদস্য সংজ্ঞাটি এর আগে থাকে template <typename T>তবে এটি একটি শিরোনামে যেতে পারে, এবং যদি তা হয় template<>তবে তা নাও হতে পারে?
ভায়োলেট জিরাফ

50

শব্দ inlineকম্পাইলার এই চিহ্নের প্রকৃত ইনলাইনিং, যা কম্পাইলার বা না করতে সিদ্ধান্ত নিতে পারেন সম্পর্কে একাধিক সংজ্ঞা রুল লঙ্ঘন করে একাধিক বস্তু ফাইল উপস্থিত থাকবে কহন সম্পর্কে বেশি।

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


22

আপনি আপনার শিরোনামে স্পষ্টভাবে একটি টেম্পলেট ইনস্ট্যান্ট করেছেন ( void Hello<T>::print_hello(T var))। এটি একাধিক সংজ্ঞা তৈরি করবে। আপনি এটি দুটি উপায়ে সমাধান করতে পারেন:

1) আপনার ইনস্ট্যান্টেশনটি ইনলাইন করুন।

2) ইনস্টলেশনটি একটি শিরোনামে ঘোষণা করুন এবং তারপরে এটি একটি সিপিতে প্রয়োগ করুন।


প্রকৃতপক্ষে একটি তৃতীয় উপায় রয়েছে যা নামবিহীন স্থানগুলিতে রাখা ... যা
সিতে

4
এটি এখানে বৈধ নয়। একটি টেম্পলেট বিশেষায়নের মূল টেমপ্লেটের মতো একই নেমস্পেসে থাকা দরকার।
এডওয়ার্ড স্ট্রেঞ্জ

0

এই ইস্যুটির সাথে সম্পর্কিত সি ++ 11 স্ট্যান্ডার্ডের কিছু অংশ এখানে রয়েছে :

কোনও ফাংশন টেমপ্লেটের স্পষ্ট স্পেশালাইজেশন কেবলমাত্র যদি ইনলাইন স্পেসিফার দিয়ে ঘোষণা করা হয় বা মুছে ফেলা হিসাবে সংজ্ঞায়িত করা হয়, এবং এর ফাংশন টেম্পলেটটি ইনলাইন কিনা তা স্বাধীনভাবেই ইনলাইন হয়। [উদাহরণ:

টেমপ্লেট শূন্য চ (টি) {/ * ... /} টেমপ্লেট ইনলাইন টি জি (টি) {/ ... * /}

টেমপ্লেট <> ইনলাইন শূন্য f <> (অন্তর্) {/ * ... /} // ঠিক আছে: ইনলাইন টেম্পলেট <> ইন্ট g <> (অন্তর্) {/ ... * /} // ঠিক আছে: ইনলাইন নয় - শেষ উদাহরণ]

সুতরাং আপনি যদি *.hফাইলে টেমপ্লেটগুলির কিছু স্পষ্ট (আর্ফ পূর্ণ) বিশেষীকরণ করেন তবে আপনাকে ওডিআরinline লঙ্ঘন থেকে মুক্তি পেতে আপনাকে এখনও সহায়তা করতে হবে ।

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