আপনি যখন C ++ 11 এ কনটেক্সট্রপ ক্ষমতাটি ব্যবহার করবেন?


337

আমার কাছে মনে হয় যে "ফাংশন কলিং" এর অর্থ ভাঙ্গা বা হ্রাসকারী "ফাংশন যা সর্বদা 5 প্রদান করে" থাকে তা হ'ল। কোনও কারণ থাকতে হবে, বা এই সক্ষমতা প্রয়োজন বা এটি সি ++ 11 এ হবে না। ওখানে কেন?

// preprocessor.
#define MEANING_OF_LIFE 42

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

আমার কাছে মনে হয় যে আমি যদি এমন একটি ফাংশন লিখি যা একটি আক্ষরিক মান ফিরিয়ে দেয় এবং আমি একটি কোড-পর্যালোচনা করতে এসেছি তবে কেউ আমাকে বলবে, তারপরে আমার 5 রিটার্ন লেখার পরিবর্তে একটি ধ্রুবক মান ঘোষণা করা উচিত।


28
আপনি কি পুনরাবৃত্তি ফাংশন সংজ্ঞা দিতে পারেন যা একটি দেয় constexpr? যদি তা হয় তবে আমি একটি ব্যবহার দেখতে পাচ্ছি।
11'11

20
আমি বিশ্বাস করি যে প্রশ্নটি "কেন একটি নতুন কীওয়ার্ড (!) প্রবর্তন করবে যদি সংকলকটি কোনও ফাংশন সংকলন সময়ে মূল্যায়ন করা যায় কি না" নিজেই তা নির্ধারণ করতে পারে "state এটি "একটি কীওয়ার্ড দ্বারা গ্যারান্টিযুক্ত" থাকা ভাল বলে মনে হয় তবে আমি মনে করি কোনও কীওয়ার্ডের প্রয়োজনীয়তা ছাড়াই যখনই সম্ভব এটির গ্যারান্টি দেওয়া পছন্দ করবো।
কোস

6
@ কোস: সি ++ ইন্টার্নালগুলির সাথে আরও কথোপকথনকারী কেউ আপনার প্রশ্নের পক্ষে পছন্দ করতে পারে তবে আমার প্রশ্নটি এমন ব্যক্তির দৃষ্টিকোণ থেকে আসে যিনি এর আগে সি কোড লিখেছেন তবে তিনি সি ++ ২০১১ কীওয়ার্ডগুলির সাথে মোটেই পরিচিত নন বা সি ++ সংকলক বাস্তবায়নের বিশদটিও নেই । সংকলক অপ্টিমাইজেশন এবং ধ্রুবক-এক্সপ্রেশন-ছাড়ের বিষয়ে যুক্তি অর্জনে সক্ষম হওয়া এইটির চেয়ে আরও উন্নত-ব্যবহারকারী প্রশ্নের বিষয় question
ওয়ারেন পি

8
@ কোস আমি আপনার মত একই রেখাগুলি ধরে ভাবছিলাম, এবং আমি যে উত্তরটি সামনে এলাম তা কনসটেক্সপ্রাইজ ছাড়াই আপনি কীভাবে জানবেন যে সংকলকটি আসলে আপনার জন্য সংকলন-সময়-মূল্যায়ন করেছে? আমি অনুমান করি যে এটি কী হয়েছে তা দেখতে আপনি সমাবেশের আউটপুটটি পরীক্ষা করতে পারেন, তবে কেবলমাত্র এই সংকলকটি বলা আপনার পক্ষে যে অপটিমাইজেশন প্রয়োজন, এটি সহজ easier এবং যদি কোনও কারণে এটি আপনার পক্ষে এটি করতে না পারে তবে এটি আপনাকে একটি সুন্দর সংকলন দেবে- আপনি যেখানে এটি অপ্টিমাইজ করার প্রত্যাশা করেছিলেন নীরবে নিখুঁতভাবে ব্যর্থ হওয়ার পরিবর্তে ত্রুটি।
জেরেমি ফ্রাইজনার

3
@ কোস: আপনিও একই কথা বলতে পারতেন const। বস্তুত, বাধ্যতামূলক অভিপ্রায় হয় দরকারী ! অ্যারের মাত্রা হ'ল ক্যানোনিকাল উদাহরণ।
অরবিট

উত্তর:


303

ধরুন এটি কিছু জটিল কিছু করে।

constexpr int MeaningOfLife ( int a, int b ) { return a * b; }

const int meaningOfLife = MeaningOfLife( 6, 7 );

এখন আপনার কাছে এমন কিছু রয়েছে যা ভাল পাঠযোগ্যতা বজায় রেখে এবং একটি সংখ্যায় ধ্রুবক স্থাপনের চেয়ে কিছুটা জটিল প্রক্রিয়াজাতকরণের অনুমতি দেওয়ার সময় ধ্রুবক পর্যন্ত মূল্যায়ন করা যায়।

এটি মূলত রক্ষণাবেক্ষণের জন্য একটি ভাল সহায়তা সরবরাহ করে কারণ এটি আপনি কী করছেন তা আরও স্পষ্ট হয়ে ওঠে। max( a, b )উদাহরণস্বরূপ নিন :

template< typename Type > constexpr Type max( Type a, Type b ) { return a < b ? b : a; }

এটি সেখানে বেশ সহজ পছন্দ তবে এর অর্থ এই নয় যে আপনি যদি কল করেন max ধ্রুবক মান দিয়ে করেন তবে এটি স্পষ্টভাবে গণনা করা হয় সংকলন সময়ে এবং রানটাইমে নয়।

আরেকটি ভাল উদাহরণ একটি DegreesToRadiansফাংশন হবে। সবাই রেডিয়ানগুলির চেয়ে পড়তে সহজ ডিগ্রী খুঁজে পায়। আপনি জানেন যে 180 ডিগ্রি রেডিয়ানে রয়েছে এটি আরও পরিষ্কারভাবে নিম্নরূপে লেখা হয়েছে:

const float oneeighty = DegreesToRadians( 180.0f );

এখানে ভাল তথ্য প্রচুর:

http://en.cppreference.com/w/cpp/language/constexpr


18
সংকলককে সংকলনের সময় মানটি চেষ্টা করে দেখার জন্য এটির সাথে দুর্দান্ত পয়েন্ট। আমি আগ্রহী কেন নির্দিষ্ট অপ্টিমাইজেশন নির্দিষ্ট করা হয় কেন কনস্ট এই কার্যকারিতাটি সরবরাহ করে না? নাকি তা করে?
TamusJRoyce

11
@ টিমাস: প্রায়শই এটি হবে তবে এটি বাধ্য নয়। কনটেক্সারপ সংকলককে বাধ্য করে এবং এটি না পারলে একটি ত্রুটি ছুঁড়ে দেবে।
Goz

20
এখন বুঝতে পারছি. পাপ (0.5) অন্য একটি। এটি পরিষ্কারভাবে সি ম্যাক্রোগুলি প্রতিস্থাপন করে।
ওয়ারেন পি

10
আমি এটি একটি নতুন সাক্ষাত্কারের প্রশ্ন হিসাবে দেখতে পারি: কনস্ট এবং কনস্টেক্সার কীওয়ার্ডের মধ্যে পার্থক্য ব্যাখ্যা করুন।
ওয়ারেন পি

2
নিজের জন্য এই পয়েন্টটি নথিভুক্ত করার একটি উপায় হিসাবে আমি অনুরূপ কোডটি উপরে এবং পুনরায় ফাংশনটি "কনস্টেক্সপ্রিপ" না করে "কনস্ট" হিসাবে লিখেছি। যেহেতু আমি Clang3.3 ব্যবহার করছি, -পেনডেন্টিক-ত্রুটিগুলি এবং -std = c ++ 11 আমি প্রত্যাশা করেছি যে পরবর্তীগুলি সংকলন করবে না। এটি "কনসেক্সেক্সার" কেস হিসাবে সংকলিত এবং চলমান ran আপনি কি মনে করেন যে এটি একটি ঝনঝন এক্সটেনশান বা পোস্টটির উত্তর দেওয়ার পর থেকেই সি ++ 11 টি স্পন্দনে কোনও টুইট হয়েছে?
আরবালেস্ট

144

ভূমিকা

constexprবাস্তবায়নটি বলার উপায় হিসাবে প্রবর্তন করা হয়নি যে এমন কিছু প্রেক্ষাপটে মূল্যায়ন করা যেতে পারে যার জন্য ধ্রুবক-প্রকাশ প্রয়োজন ; মানানসই বাস্তবায়ন সি ++ 11 এর আগে এটি প্রমাণ করতে সক্ষম হয়েছে।

কিছু একটি বাস্তবায়ন প্রমাণ করতে পারে অভিপ্রায় কোডের একটি নির্দিষ্ট অংশ:

  • এটি কী যে বিকাশকারী এই সত্তার সাথে প্রকাশ করতে চান?
  • কাজটি ঘটে যাওয়ার কারণে কি আমাদের অন্ধভাবে কোডটি একটি ধ্রুবক-অভিব্যক্তিতে ব্যবহার করার অনুমতি দেওয়া উচিত ?

পৃথিবী ছাড়া কী হত constexpr ?

ধরা যাক আপনি একটি লাইব্রেরি বিকাশ করছেন এবং বুঝতে পারবেন যে আপনি বিরতিতে প্রতিটি পূর্ণসংখ্যার যোগফল গণনা করতে সক্ষম হতে চান (0,N]

int f (int n) {
  return n > 0 ? n + f (n-1) : n;
}

অভিপ্রায় অভাব

একটি সংকলক সহজেই প্রমাণ করতে পারে যে উপরের ফাংশনটি ধ্রুবক-প্রকাশে কলযোগ্য করতে পারে যদি পাস করার জানা যায়; তবে আপনি এটিকে উদ্দেশ্য হিসাবে ঘোষণা করেননি - এটি ঘটনাটি ঘটেছে।

এখন অন্য কেউ আসেন, আপনার ফাংশনটি পড়েন, সংকলকের মতো একই বিশ্লেষণ করেন; " ওহ, এই ক্রিয়াটি ধ্রুবক-অভিব্যক্তিতে ব্যবহারযোগ্য!" , এবং নিম্নলিখিত কোড টুকরা লিখুন।

T arr[f(10)]; // freakin' magic

অপ্টিমাইজেশন

আপনি একজন "দুর্দান্ত" লাইব্রেরি বিকাশকারী হিসাবে সিদ্ধান্ত নেবেন যে fপ্রার্থনার সময় ফলাফলটি ক্যাশে করা উচিত; একই মানগুলি বারবার গণনা করতে চাইবে কে?

int func (int n) { 
  static std::map<int, int> _cached;

  if (_cached.find (n) == _cached.end ()) 
    _cached[n] = n > 0 ? n + func (n-1) : n;

  return _cached[n];
}

ফলাফল

আপনার নিখুঁত অপ্টিমাইজেশন প্রবর্তন করে, আপনি কেবল আপনার ফাংশনটির প্রতিটি ব্যবহার ভেঙে ফেলেছেন যা এমন প্রসঙ্গে হয়েছে যেখানে একটি ধ্রুবক-প্রকাশ প্রয়োজন।

আপনি কখনও প্রতিশ্রুতি দেননি যে ক্রিয়াটি একটি ধ্রুবক-প্রকাশের ক্ষেত্রে ব্যবহারযোগ্য , এবং ছাড়া constexprএই জাতীয় প্রতিশ্রুতি দেওয়ার কোনও উপায় থাকবে না।


তাহলে, আমাদের কেন দরকার constexpr?

প্রাথমিক ব্যবহার constexpr ঘোষণা হয় অভিপ্রায়

যদি কোনও সত্তা হিসাবে চিহ্নিত না হয় constexpr- এটি কখনও ধ্রুবক-অভিব্যক্তিতে ব্যবহারের উদ্দেশ্যে নয় ; এবং তা থাকলেও, আমরা এই জাতীয় প্রসঙ্গটি নির্ণয়ের জন্য সংকলকটির উপর নির্ভর করি (কারণ এটি আমাদের উদ্দেশ্যকে উপেক্ষা করে)।


25
এটি সম্ভবত সঠিক উত্তর, যেহেতু সি ++ 14 এবং সি ++ 17 এর সাম্প্রতিক পরিবর্তনগুলি ভাষার আরও বিস্তৃত পরিসরকে constexprপ্রকাশের জন্য ব্যবহার করতে দেয় । অন্য কথায়, প্রায় কাছাকাছি কিছু সটীক করা যেতে পারে constexpr(হয়তো একদিন এটা শুধু শুধু দূরে এই কারণে যাবে?), এবং যদি না এক যখন ব্যবহার করতে একটি নির্ণায়ক হয়েছে constexprবা না প্রায় কাছাকাছি সব কোডের যেমন লেখা হবে ।
আলেকোভ

4
@alecov Definitly সবকিছু না ... I/O, syscallএবং dynamic memory allocationdefinitly হিসেবে চিহ্নিত করা সূত্র 't constexprএছাড়া সবকিছু উচিত হবে constexpr
জিয়াআওও জু

1
@ আলেকভ কিছু ফাংশন রানটাইমে মৃত্যুদন্ড কার্যকর করার জন্য বোঝানো হয় এবং সংকলন সময়ে এটি করা অর্থহীন।
জিয়াআওও জু

1
আমি এই উত্তরটিও সবচেয়ে পছন্দ করি। সংকলন সময় মূল্যায়ন একটি ঝরঝরে অপ্টিমাইজেশন, কিন্তু আপনি সত্যিই যা পাবেন তা constexprহ'ল একরকম আচরণের গ্যারান্টি। ঠিক যেমন constকরে।
টোমা জ্যাটো - মনিকা

কোন সংকলক এই কনটেক্সটপ্রস-কম সংস্করণটি মঞ্জুরি দেয় int f (int n) { return n > 0 ? n + f (n-1) : n;} T arr[f(10)]; তা আমি কোথাও সংকলন করতে পারি না?
জের

91

নিন std::numeric_limits<T>::max(): যে কারণেই হোক না কেন, এটি একটি পদ্ধতি। constexprএখানে উপকারী হবে।

অন্য উদাহরণ: আপনি একটি সি-অ্যারে (বা ক std::array) ঘোষণা করতে চান যা অন্য অ্যারের মতো বড়। এই মুহুর্তে এটি করার উপায়টি এরকম:

int x[10];
int y[sizeof x / sizeof x[0]];

তবে এটি লিখতে সক্ষম হওয়াই ভাল না:

int y[size_of(x)];

ধন্যবাদ constexpr, আপনি করতে পারেন:

template <typename T, size_t N>
constexpr size_t size_of(T (&)[N]) {
    return N;
}

1
চমৎকার টেমপ্লেট ব্যবহারের জন্য +1, কিন্তু কনস্টেক্সপ্র ছাড়া এটি ঠিক একই রকম কাজ করবে, তাই না?
কোস

21
@ কোস: না। এটি রানটাইমের মান ফেরত দেবে। constexprকম্পাইলারকে ফাংশনটি একটি সংকলন-সময় মান (যদি তা পারে) ফেরত দিতে বাধ্য করে।
deft_code

14
@ কোস: constexprফাংশন কলের ফলাফলটি একটি সংকলন-সময় ধ্রুবক কিনা তা নির্বিশেষে এটি কোনও অ্যারে আকারের ঘোষণায় বা টেম্পলেট যুক্তি হিসাবে ব্যবহার করা যাবে না। এই দুটি মূলত একমাত্র ব্যবহারের ক্ষেত্রে constexprতবে কমপক্ষে টেমপ্লেট আর্গুমেন্ট ব্যবহারের ক্ষেত্রে গুরুত্বপূর্ণ।
কনরাড রুডল্ফ

2
"যে কারণেই হোক না কেন, এটি একটি পদ্ধতি": কারণটি হ'ল সি ++ ০৩ তে কেবল সংকলন টাইম পূর্ণসংখ্যার উপস্থিতি রয়েছে, তবে অন্য কোনও সংকলনের সময় প্রকার নেই, সুতরাং কেবলমাত্র একটি পদ্ধতি সি ++ 11 এর পূর্বে স্বেচ্ছাচারী ধরণের জন্য কাজ করতে পারে।
সেবাস্তিয়ান মাচ

5
@ লুইচুই না, এটি "ঠিক আছে" নয়: কিছু বিষয় সম্পর্কে জিসিসি ডিফল্টরূপে খুব শিথিল। -pedanticবিকল্পটি ব্যবহার করুন এবং এটি একটি ত্রুটি হিসাবে পতাকাঙ্কিত হবে।
কনরাড রুডল্ফ

19

constexprফাংশনগুলি সত্যিই দুর্দান্ত এবং সি ++ এর জন্য একটি দুর্দান্ত সংযোজন। তবে, আপনি ঠিক বলেছেন যে এটি সমাধান করে এমন বেশিরভাগ সমস্যাটি ম্যাক্রোগুলির সাথে অকার্যকরভাবে কাজ করা যেতে পারে।

তবে এর ব্যবহারগুলির মধ্যে একটিতে constexprসি ++ 03 সমতুল্য, টাইপড ধ্রুবক নেই।

// This is bad for obvious reasons.
#define ONE 1;

// This works most of the time but isn't fully typed.
enum { TWO = 2 };

// This doesn't compile
enum { pi = 3.1415f };

// This is a file local lvalue masquerading as a global
// rvalue.  It works most of the time.  But May subtly break
// with static initialization order issues, eg pi = 0 for some files.
static const float pi = 3.1415f;

// This is a true constant rvalue
constexpr float pi = 3.1415f;

// Haven't you always wanted to do this?
// constexpr std::string awesome = "oh yeah!!!";
// UPDATE: sadly std::string lacks a constexpr ctor

struct A
{
   static const int four = 4;
   static const int five = 5;
   constexpr int six = 6;
};

int main()
{
   &A::four; // linker error
   &A::six; // compiler error

   // EXTREMELY subtle linker error
   int i = rand()? A::four: A::five;
   // It not safe use static const class variables with the ternary operator!
}

//Adding this to any cpp file would fix the linker error.
//int A::four;
//int A::six;

12
আপনি কি দয়া করে স্পষ্ট করে বলতে পারেন যে "অতি সূক্ষ্ম লিঙ্কার ত্রুটি"? বা কমপক্ষে কোনও স্পষ্টির জন্য একটি পয়েন্টার সরবরাহ করবেন?
এনোবায়রাম

4
@enobayram, টের্নারি অপারেটর অপারেন্ডগুলির ঠিকানা নেয়। এটি কোড থেকে সুস্পষ্ট নয়। সবকিছু সূক্ষ্ম সংকলন করে তবে লিঙ্কটি ব্যর্থ হয় কারণ ঠিকানাটি fourসমাধান করে না। আমার static constভেরিয়েবলের ঠিকানাটি কে নিচ্ছে তা সত্যই আমাকে খনন করতে হয়েছিল ।
ডিফ্ট_কোড

23
"এটি সুস্পষ্ট কারণে খারাপ": সবচেয়ে স্পষ্ট কারণটি সেমিকোলন হ'ল, তাই না?
টনিকে

4
"অতি সূক্ষ্ম লিঙ্কার ত্রুটি" আমাকে পুরোপুরি বিস্মিত করেছে। আমরাও fourনা fiveসুযোগ রয়েছে।
স্টিভেন লু

3
নতুন enum classপ্রকারটিও দেখুন, এটি এনামের কয়েকটি সমস্যা সমাধান করে।
নিনমনেকি

14

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

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

সম্পাদনা:

এসও-তে ঘুরে বেড়ানোর পরে, দেখে মনে হচ্ছে অন্যরা কনটেক্সার্সের মাধ্যমে কী কী সম্ভব তার কয়েকটি উদাহরণ নিয়ে এসেছে।


"একটি ইন্টারফেসের অংশ হতে আপনি একটি ফাংশন হতে হবে"?
ড্যানিয়েল আরউইকার

এখন যেহেতু আমি এর কার্যকারিতা দেখতে পাচ্ছি, আমি সি ++ 0 এক্স সম্পর্কে আরও কিছুটা উত্তেজিত। এটি একটি ভাল চিন্তা চিন্তা জিনিস মনে হচ্ছে। আমি জানতাম তাদের অবশ্যই হবে। সেই ভাষাগুলির স্ট্যান্ডার্ড উবার-গিক্স খুব কমই এলোমেলো জিনিস করে।
ওয়ারেন পি

আমি ল্যাম্বডাস, থ্রেডিং মডেল, ইনিশিয়ালার_লিস্ট, মূলসূত্র উল্লেখ, বৈকল্পিক টেম্পলেট, নতুন বাইন্ড ওভারলোডগুলি সম্পর্কে আরও উত্সাহিত ... এর অপেক্ষায় বেশ কিছুটা আছে।
luke

1
হ্যাঁ, তবে আমি ইতিমধ্যে বেশ কয়েকটি অন্যান্য ল্যাঙ্গুয়েজে ল্যাম্বডাস / ক্লোজারগুলি বুঝতে পেরেছি। constexprএকটি শক্তিশালী সংকলন-সময় এক্সপ্রেশন মূল্যায়ন সিস্টেম সহ একটি সংকলকটিতে আরও বিশেষভাবে কার্যকর। সি ++ এর সেই ডোমেনে সত্যিই কোনও সমবয়সী নেই। (এটি সি ++ 11, আইএমএইচওর জন্য একটি দৃ strong় প্রশংসা)
ওয়ারেন পি

11

"গাইটিং নেটিভ ২০১২" এ স্ট্রাস্ট্রপের ভাষণ থেকে:

template<int M, int K, int S> struct Unit { // a unit in the MKS system
       enum { m=M, kg=K, s=S };
};

template<typename Unit> // a magnitude with a unit 
struct Value {
       double val;   // the magnitude 
       explicit Value(double d) : val(d) {} // construct a Value from a double 
};

using Speed = Value<Unit<1,0,-1>>;  // meters/second type
using Acceleration = Value<Unit<1,0,-2>>;  // meters/second/second type
using Second = Unit<0,0,1>;  // unit: sec
using Second2 = Unit<0,0,2>; // unit: second*second 

constexpr Value<Second> operator"" s(long double d)
   // a f-p literal suffixed by ‘s’
{
  return Value<Second> (d);  
}   

constexpr Value<Second2> operator"" s2(long double d)
  // a f-p literal  suffixed by ‘s2’ 
{
  return Value<Second2> (d); 
}

Speed sp1 = 100m/9.8s; // very fast for a human 
Speed sp2 = 100m/9.8s2; // error (m/s2 is acceleration)  
Speed sp3 = 100/9.8s; // error (speed is m/s and 100 has no unit) 
Acceleration acc = sp1/0.5s; // too fast for a human

2
এই উদাহরণটি স্ট্রস্ট্রাপের কাগজের সফটওয়্যার ডেভলপমেন্ট ফর ইনফ্রাস্ট্রাকচারে পাওয়া যায় ।
ম্যাথিউ পোলিট

ঝনঝন -৩.৩: ত্রুটি: কনটেক্সটপ্রাপ্ত ফাংশনের রিটার্ন টাইপ 'মান <সেকেন্ড>' আক্ষরিক ধরণের নয়
মিতজা

এটি দুর্দান্ত তবে কে এই জাতীয় কোডগুলিতে আক্ষরিক রাখে। আপনার সংকলকটি "আপনার ইউনিটগুলি পরীক্ষা করুন" রাখার জন্য আপনি যদি কোনও ইন্টারেক্টিভ ক্যালকুলেটর লিখছিলেন তবে তা বোঝা যাবে।
বোবোবোবো

5
@ বোবোবো বা আপনি যদি মঙ্গল জলবায়ু অরবিটারের জন্য ন্যাভিগেশন সফ্টওয়্যার লিখছিলেন তবে :)
জেরেমি ফ্রাইজনার

1
এটি সংকলন করতে - ১. আক্ষরিক প্রত্যয়গুলিতে আন্ডারস্কোর ব্যবহার করুন। 2. 100_ মিটার জন্য অপারেটর "" _m যোগ করুন। ৩.০.০_ মি ব্যবহার করুন, বা একটি ওভারলোড যুক্ত করুন যা স্বাক্ষরবিহীন দীর্ঘকে স্বীকার করে। ৪) মান নির্মাতা কনসেক্সপ্রেস ঘোষণা করুন। ৫. সংশ্লিষ্ট অপারেটর / এর মতো মান শ্রেণিতে যুক্ত করুন: কনটেক্সপ্রিপ অটো অপারেটর / (কনস্ট মান <Y> এবং অন্যান্য) কনস্ট-রিটার্ন মান <ইউনিট <দ্য ইউনিট :: মি - মান <Y> :: TheUnit :: m, TheUnit :: কেজি - মান <Y> :: TheUnit :: কেজি, TheUnit :: s - মান <Y> :: TheUnit :: s >> (ভাল / অন্যান্য। মূল্য); }। যেখানে মান শ্রেণীর ভিতরে ইউনিট যুক্ত করার জন্য টাইপইফ হয় is
0kcats

8

আর একটি ব্যবহার (এখনও উল্লেখ করা হয়নি) হয় constexprনির্মাণকারী। এটি রানটাইম চলাকালীন আরম্ভ করতে হবে না এমন সংকলন সময় স্থিরতা তৈরি করতে দেয় allows

const std::complex<double> meaning_of_imagination(0, 42); 

ব্যবহারকারীর সংজ্ঞায়িত আক্ষরিক সহ আপনার যুক্ত করুন এবং আক্ষরিক ব্যবহারকারীর সংজ্ঞায়িত শ্রেণীর জন্য আপনার সম্পূর্ণ সমর্থন রয়েছে।

3.14D + 42_i;

6

রূপকগুলির সাথে একটি প্যাটার্ন থাকত:

template<unsigned T>
struct Fact {
    enum Enum {
        VALUE = Fact<T-1>*T;
    };
};

template<>
struct Fact<1u> {
    enum Enum {
        VALUE = 1;
    };
};

// Fact<10>::VALUE is known be a compile-time constant

আমি বিশ্বাস করি constexprযে আপনাকে বিশেষায়িতকরণ, SFINAE এবং স্টাফ সহ টেমপ্লেট এবং অদ্ভুত কনস্ট্রাক্টের প্রয়োজন ছাড়াই এই জাতীয় নির্মাণগুলি লিখতে দিয়েছিলেন - তবে ঠিক আপনি পছন্দ করেন একটি রান-টাইম ফাংশন লিখতে, তবে গ্যারান্টি সহ যে ফলাফলটি সংকলনটিতে নির্ধারিত হবে -time।

তবে, নোট করুন:

int fact(unsigned n) {
    if (n==1) return 1;
    return fact(n-1)*n;
}

int main() {
    return fact(10);
}

এটি দিয়ে সংকলন করুন g++ -O3এবং আপনি এটি দেখতে পাবেনfact(10) সংকলন করুন এটি সংকলন সময়ে সত্যই উত্সাহিত করা হয়েছে!

একটি ভিএলএ-সচেতন সংকলক (সুতরাং C99 মোডে সি সংকলক বা C99+ সংযোজন সহ সি ++ সংকলক) এমনকি আপনাকে এটি করার অনুমতি দিতে পারে:

int main() {
    int tab[fact(10)];
    int tab2[std::max(20,30)];
}

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


সংকলন-সময়ে ফ্যাক্ট ফাংশনটি মূল্যায়ন করা হয় না। এটি কনস্টেক্সপ্র হওয়া দরকার এবং এটির জন্য কেবলমাত্র একটি রিটার্ন স্টেটমেন্ট থাকতে হবে।
সুমেন্ট

1
@ সুমান্ট: আপনি ঠিক বলেছেন যে এটি সংকলন-সময়ে মূল্যায়ন করতে হবে না, তবে এটি! আমি কম্পাইলারগুলিতে আসলে কী ঘটেছিল তা উল্লেখ করছিলাম। এটি সাম্প্রতিক জিসিসিতে সংকলন করুন, ফলাফল asm দেখুন এবং আপনি আমাকে বিশ্বাস না করেন কিনা তা নিজের জন্য পরীক্ষা করুন!
কোস

সংযোজন করার চেষ্টা করুন std::array<int, fact(2)>এবং আপনি দেখতে পাবেন যে সংকলন-সময়ে মূল্যায়ন করা হয়নি ()। এটি কেবলমাত্র জিসিসি অপ্টিমাইজার একটি ভাল কাজ করছে।

1
আমি যা বলেছিলাম ... আমি কি সত্যিই অস্পষ্ট? শেষ অনুচ্ছেদটি দেখুন
কোস

5

কেবলমাত্র একটি প্রকল্পকে সি ++ 11 এ স্যুইচ করা শুরু করেছেন এবং কনস্টেক্সপ্রের জন্য পুরোপুরি একটি ভাল পরিস্থিতি এসে গেছে যা একই ক্রিয়াকলাপের বিকল্প পদ্ধতিগুলি পরিষ্কার করে। এখানে মূল বক্তব্যটি হ'ল ফাংশনটি কেবল অ্যারে আকারের ঘোষণার মধ্যে রাখতে হবে যখন এটি কনটেক্সপ্রিপ হিসাবে ঘোষণা করা হয়। বেশ কয়েকটি পরিস্থিতি রয়েছে যেখানে আমি দেখতে পাচ্ছি যে আমি কোডের ক্ষেত্রের সাথে জড়িত রয়েছি তার সাথে এগিয়ে চলতে এটি খুব দরকারী।

constexpr size_t GetMaxIPV4StringLength()
{
    return ( sizeof( "255.255.255.255" ) );
}

void SomeIPFunction()
{
    char szIPAddress[ GetMaxIPV4StringLength() ];
    SomeIPGetFunction( szIPAddress );
}

4
এটি সমানভাবে লেখা যেতে পারে: কনট সাইজ_ট ম্যাক্সআইপিভি 4 স্ট্রিংলেন্থ = আকারের ("255.255.255.255");
সুপারফ্লাই জন

static inline constexpr const autoসম্ভবত ভাল।
জিয়াহাও Xu

3

অন্যান্য সমস্ত উত্তর দুর্দান্ত, আমি আশ্চর্যজনক যে কনস্টেক্সপ্রের সাথে আপনি যা করতে পারেন তার একটি দুর্দান্ত উদাহরণ দিতে চাই। দেখুন-ফিট ( https://github.com/rep-movsd/see-phit/blob/master/seephit.h ) একটি সংকলন সময় এইচটিএমএল পার্সার এবং টেম্পলেট ইঞ্জিন। এর অর্থ আপনি এইচটিএমএল লাগাতে পারেন এবং এমন একটি গাছ বের করতে পারেন যা ম্যানিপুলেট করতে সক্ষম। সংকলনের সময় পার্সিং করা আপনাকে কিছুটা অতিরিক্ত পারফরম্যান্স দিতে পারে।

গিথুব পৃষ্ঠার উদাহরণ থেকে:

#include <iostream>
#include "seephit.h"
using namespace std;



int main()
{
  constexpr auto parser =
    R"*(
    <span >
    <p  color="red" height='10' >{{name}} is a {{profession}} in {{city}}</p  >
    </span>
    )*"_html;

  spt::tree spt_tree(parser);

  spt::template_dict dct;
  dct["name"] = "Mary";
  dct["profession"] = "doctor";
  dct["city"] = "London";

  spt_tree.root.render(cerr, dct);
  cerr << endl;

  dct["city"] = "New York";
  dct["name"] = "John";
  dct["profession"] = "janitor";

  spt_tree.root.render(cerr, dct);
  cerr << endl;
}

1

আপনার মৌলিক উদাহরণটি তাদের কাছে ধ্রুবকের মত একই যুক্তি উপস্থাপন করে। কেন ব্যবহার

static const int x = 5;
int arr[x];

উপর

int arr[5];

কারণ এটি আরও রক্ষণাবেক্ষণের উপায়। কনসেক্সেক্সপ্র ব্যবহার বিদ্যমান রূপক কৌশলগুলির তুলনায় অনেক বেশি দ্রুত লেখা এবং পড়ার পক্ষে।


0

এটি কিছু নতুন অপ্টিমাইজেশন সক্ষম করতে পারে। consttraditionতিহ্যগতভাবে টাইপ সিস্টেমের জন্য একটি ইঙ্গিত, এবং এটি অপ্টিমাইজেশনের জন্য ব্যবহার করা যায় না (যেমন কোনও constসদস্য ফাংশন পারে)const_cast আইনানুগভাবে যেকোন উপায়ে অবজেক্টটি সংশোধন এবং পরিবর্তন constকরতে পারে , সুতরাং অপ্টিমাইজেশনের জন্য বিশ্বাস করা যায় না)।

constexprসত্যই প্রকাশ ধ্রুবক, যদি ফাংশনের ইনপুটগুলি কনস্ট থাকে। বিবেচনা:

class MyInterface {
public:
    int GetNumber() const = 0;
};

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

যোগ করা হচ্ছে constexpr:

class MyInterface {
public:
    constexpr int GetNumber() const = 0;
};

সংকলকটি এখন একটি অপ্টিমাইজেশন প্রয়োগ করতে পারে যেখানে রিটার্নের মান GetNumber()ক্যাশে হয় এবং এতে অতিরিক্ত কলগুলি মুছে ফেলা যায় GetNumber(), কারণ constexprএটির আরও দৃ stronger় গ্যারান্টি হ'ল যে ফেরতের মান পরিবর্তন হবে না।


প্রকৃতপক্ষে অপ্টিমাইজেশনে ব্যবহার করা const যেতে পারে ... আইআইআরসি-র পরেও কোনও মান সংজ্ঞায়িত কনস্টিকে সংশোধন করা এটি const_castঅপরিজ্ঞাত আচরণ। আমি এটি constসদস্য ফাংশনগুলির জন্য সামঞ্জস্যপূর্ণ আশা করব , তবে আমার এটি স্ট্যান্ডার্ডের সাথে পরীক্ষা করা দরকার। এর অর্থ হ'ল সংকলকটি নিরাপদে সেখানে অপ্টিমাইজেশন করতে পারে।
কোস

1
@ ওয়ারেন: অপ্টিমাইজেশন আসলে করা হয়েছে কিনা তা বিবেচ্য নয়, এটি কেবল অনুমোদিত। @ কোস: এটি একটি সামান্য জ্ঞাত সূক্ষ্মতা যে মূল বস্তুটি কনস্ট ( বনাম ) হিসাবে ঘোষণা করা হয় না , তবে এটির পয়েন্টার / রেফারেন্সে দূরে কনস্টের মাধ্যমে এটিকে সংশোধন করা নিরাপদ । অন্যথায়, সর্বদা অপরিবর্তিত আচরণটি চালিত করা এবং অকেজো হতে হবে :) এই ক্ষেত্রে, সংকলকটির কাছে মূল অবজেক্টের কনস্ট-নেস সম্পর্কিত কোনও তথ্য নেই, তাই এটি বলতে পারে না। int xconst int xconst_castconst_cast
অ্যাশলেস ব্রেন

@ কোস আমি এখানে কনস্ট_কাস্ট একমাত্র সমস্যা বলে মনে করি না। কনস্ট পদ্ধতিটি বিশ্বব্যাপী ভেরিয়েবলটি পড়তে এবং সংশোধন করার অনুমতি দেয়। বিপরীতভাবে, অ্যান্থার থ্রেডের কেউ কলগুলির মধ্যে কনস্টের অবজেক্টটিও পরিবর্তন করতে পারে।
এনোবায়রাম

1
"= 0" এখানে বৈধ নয় এবং এটি সরানো উচিত। আমি নিজে এটি করব, তবে আমি নিশ্চিত নই যে এটি এসও প্রোটোকলের সাথে সামঞ্জস্যপূর্ণ।
জানুন সমস্ত ওয়ানবনেব

উভয় উদাহরণই অবৈধ: প্রথমটির ( int GetNumber() const = 0;) GetNumber()পদ্ধতিটি ভার্চুয়াল হিসাবে ঘোষণা করা উচিত । দ্বিতীয় ( constexpr int GetNumber() const = 0;) বৈধ নয় কারণ খাঁটি স্পেসিফায়ার ( = 0) পদ্ধতিটি ভার্চুয়াল হতে বোঝায়, তবে কনটেক্সপ্রসগুলি ভার্চুয়াল হতে হবে না (রেফার: en.cppreferences.com/w/cpp/language/constexpr )
stj

-1

কখন ব্যবহার করবেন constexpr:

  1. একটি সংকলন সময় ধ্রুবক যখনই আছে।

যদিও আমি আপনার সাথে একমত, এই উত্তরটি ব্যাখ্যা করে না যে constexpr প্রিপ্রোসেসর ম্যাক্রোগুলির চেয়ে কেন পছন্দ করা উচিত const
স্নেফটেল

-3

এটি ভালো কিছু জন্য দরকারী

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

int some_arr[MeaningOfLife()];

এটি একটি বৈশিষ্ট্য শ্রেণীর বা এর মতো দিয়ে বেঁধে রাখুন এবং এটি বেশ কার্যকর হয়ে ওঠে।


4
আপনার উদাহরণে এটি একটি সরল ধ্রুবকের চেয়ে শূন্য সুবিধা দেয়, সুতরাং এটি সত্যই প্রশ্নের উত্তর দেয় না।
jalf

এটি একটি স্বতঃস্ফূর্ত উদাহরণ, কল্পনা করুন যে অর্থ-অফলাইফ () অন্য কোথাও থেকে এর মান পেয়ে যায়, অন্য কোনও ফাংশন বা একটি # নির্দিষ্ট বা সিরিজ থ্রোফ বলুন। এটি কী ফেরায় তা আপনি জানেন না, এটি লাইব্রেরির কোড হতে পারে। অন্যান্য উদাহরণ, একটি অপরিবর্তনীয় পাত্রে কল্পনা করুন যার একটি কনস্টেক্সপ্রাইজ আকার () পদ্ধতি রয়েছে। আপনি এখন int আরআর করতে পারেন [ধারক.সাইজ ()];
প্লিভসি

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