সি ++ এ কীভাবে শর্তসাপেক্ষ টাইপএফ তৈরি করবেন


90

আমি এরকম কিছু করার চেষ্টা করছি:

#include <iostream>
#include <random>

typedef int Integer;

#if sizeof(Integer) <= 4
    typedef std::mt19937     Engine;
#else
    typedef std::mt19937_64  Engine;
#endif

int main()
{
    std::cout << sizeof(Integer) << std::endl;
    return 0;
}

তবে আমি এই ত্রুটি পেয়েছি:

error: missing binary operator before token "("

আমি কীভাবে সঠিকভাবে শর্তসাপেক্ষ টাইপএফ তৈরি করতে পারি?


25
প্রিপ্রোসেসর sizeof, বা অন্যান্য সি ++ নির্মাণ সম্পর্কে কিছুই জানে না । আপনি নিজের দ্বারা যে জিনিসগুলি তৈরি করেছেন সে সম্পর্কে এটি অবশ্যই জানে না typedef, কারণ এটি এখনও পার্স করা হয়নি।
অরবিটে লাইটনেস রেস

4
আপনি শর্তসাপেক্ষে টাইপিডেফগুলি সংজ্ঞায়িত করতে enable_ifবা ব্যবহার করতে পারেন conditionalতবে আপনি এর জন্য প্রিপ্রসেসর ব্যবহার করতে পারবেন না।
বারটেক বানাচেউইচিজ

4
@ লাইটনেসেসিনঅরবিট: প্রাক প্রসেসিং এবং সংকলনটি জিসিসিতে সংহত করা হয়েছে, সুতরাং এটি কেবল নিশ্চিত নয় যে সফ্টওয়্যার প্রসেসিং কোডটি ব্যবহারকারী-তৈরি প্রকারের সংজ্ঞাগুলি সম্পর্কে জানে না তবে জিসিসির ক্ষেত্রে এটি মিথ্যা হিসাবে পরিচিত। কারণ sizeofএকটি প্রাক প্রসেসর অবস্থায় কাজ করতে পারবেন না কারণ ভাষা যে ভাবে, কিভাবে একটি বাস্তবায়ন কাজ না কারণ সংজ্ঞায়িত করা হয়।
এরিক পোস্টপিসিল

4
@ লাইটনেসেসেসিনআরবিট: অনুবাদ পর্যায়ক্রমে সিনট্যাক্স এবং শব্দার্থবিজ্ঞানের সংজ্ঞা দেওয়া হয়েছে, প্রক্রিয়াজাতকরণের ক্রম নয়। প্রতি সি ++ ২০১১ (এন ৩০৯২) ২.২ [লেকস.ফেসস] নোট ১১, "বাস্তবায়নের ক্ষেত্রে অবশ্যই এই পৃথক পর্যায়ের ঘটনাগুলি এমনভাবে আচরণ করা উচিত, যদিও বাস্তবে বিভিন্ন ধাপ একসাথে ভাঁজ করা যেতে পারে” " জিসিসি সম্পর্কে আমার বক্তব্য প্রাসঙ্গিক কারণ এটি প্রমাণ করে যে আপনার দাবি এইভাবেই বাস্তবায়ন কার্যকর করে। অন্য কথায়, আপনার মন্তব্য দাবি করেছে যে একটি বাস্তবায়নের একটি বিশেষ পদ্ধতি এটি প্রতিরোধ করে। তবে এটি বাস্তবায়ন নয় যা এটি প্রতিরোধ করে (আমরা এটি করতে পারতাম ); এটি ভাষার সংজ্ঞা।
এরিক পোস্টপিসিল

4
@ এরিক: আমার বাস্তবায়ন সম্পর্কে যা কিছু হোক না কেন দাবি করার অর্থ ছিল না। আমি অবশ্যই কোন নির্দিষ্ট একটি উল্লেখ না। আমার মন্তব্যে এমন একটি আচরণ বলা হয়েছে যা আপনার নিজের মতো করে বিধি-বিধানের সাপেক্ষে। আমি মনে করি না যে আমরা আসলে এখানে কোনও বিষয়ে দ্বিমত পোষণ করছি - আপনার ভাষা আইনীকরণ সম্ভবত আয়না থেকে এসেছিল। :)
অরবিটে হালকা ঘোড়দৌড়

উত্তর:


139

std::conditionalসি ++ 11 থেকে মেটা-ফাংশনটি ব্যবহার করুন ।

#include <type_traits>  //include this

typedef std::conditional<sizeof(int) <= 4,
                         std::mt19937,
                         std::mt19937_64>::type Engine;

মনে রাখবেন যে আপনি যে ধরণটি ব্যবহার করেন sizeofতা যদি কোনও টেম্পলেট প্যারামিটার হয় Tতবে বলুন , তাহলে আপনাকে এই typenameহিসাবে ব্যবহার করতে হবে :

typedef typename std::conditional<sizeof(T) <= 4, // T is template parameter
                                  std::mt19937,
                                  std::mt19937_64>::type Engine;

বা এর Engineউপর নির্ভর করে T:

template<typename T>
using Engine = typename std::conditional<sizeof(T) <= 4, 
                                         std::mt19937,
                                         std::mt19937_64>::type;

এটি নমনীয় , কারণ এখন আপনি এটি হিসাবে এটি ব্যবহার করতে পারেন:

Engine<int>  engine1;
Engine<long> engine2;
Engine<T>    engine3; // where T could be template parameter!

4
+1 গৌণ নিটপিক: 64৪ sizeof(int) <= 4-বিট উইন্ডোজ মেশিনের জন্য চেক করা খুব পোর্টেবল উপায় নয়, জিসিসি (মিনজিডাব্লু) x64 সংকলক দেয় sizeof(int) = sizeof(long) = 4। আরও ভাল উপায় হবে sizeof(void*) <= 4
কিংবদন্তি 2 কে

@ কিংবদন্তি 2 কে: আপনার মানে Engine<void*> engine4;? ;-)
নওয়াজ

4
@ নাওয়াজ: অবশ্যই নয় :) আমি std::conditional<sizeof(void*) <= 4, std::mt19937, std::mt19937_64>প্রথম কোড স্নিপেটকে বোঝাতে চাইছিলাম ।
কিংবদন্তি 2 কে

4
@ কিংবদন্তি 2 কে: আপনি যদি এটি সরবরাহ করে থাকেন তবে আপনি কেন এটি ব্যবহার করবেন Engine<void*>? : পি
নওয়াজ

@ নাওয়াজ: হাহাহা ... এটা সত্য। যাইহোক, আমি একটি আকারের উপর ভিত্তি স্থাপত্য সনাক্ত করার সময় চিন্তা ওপি সম্ভবত ফাঁদ জানা উচিত int:)
legends2k

35

std::conditionalআপনি ব্যবহার করে এটি এর মতো করতে পারেন:

using Engine = std::conditional<sizeof(int) <= 4, 
                               std::mt19937, 
                               std::mt19937_64
                               >::type;

আপনি যদি একটি করতে চান তবে আপনি typedefএটিও করতে পারেন।

typedef std::conditional<sizeof(int) <= 4, 
                         std::mt19937, 
                         std::mt19937_64
                         >::type Engine

এখানে কোনও প্রয়োজন typenameনেই
gx_

@gx_ হ্যাঁ, এটি টেমপ্লেটগুলির সাথে কাজ করা থেকে কংক্রিটের ধরণের নয় putting
Rapptz

4
ভালো লাগবে
Rapptz

5

আপনার যদি সি ++ 11 উপলভ্য না থাকে (যদিও আপনি এটি ব্যবহার করার পরিকল্পনা করছেন বলে মনে হয় std::mt19937), তবে আপনি বুস্ট মেটাপ্রোগ্র্যামিং লাইব্রেরি (এমপিএল) ব্যবহার করে সি ++ 11 সমর্থন ছাড়াই একই জিনিসটি প্রয়োগ করতে পারেন । এখানে একটি সংকলনযোগ্য উদাহরণ:

#include <boost/mpl/if.hpp>
#include <iostream>
#include <typeinfo>

namespace mpl = boost::mpl;

struct foo { };
struct bar { };

int main()
{
    typedef mpl::if_c<sizeof(int) <= 4, foo, bar>::type Engine;

    Engine a;
    std::cout << typeid(a).name() << std::endl;
}

এটি fooআমার সিস্টেমে মঙ্গলের নামটি প্রিন্ট করে , যেমন intএখানে 4 বাইট।


4
আপনি if_cপরিবর্তে ব্যবহার করবেন না কেন ? এটা তোলে লিখতে হবে সহজ হবে (ও বুঝতে): mpl::if_c<sizeof(int)<=4, foo, bar>::type। তাই না?
নওয়াজ

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