টাইম স্ট্রিং হ্যাশিং কম্পাইল করুন


102

আমি কয়েকটি ভিন্ন জায়গায় পড়েছি যে সি ++ 11 এর নতুন স্ট্রিং লিটারেল ব্যবহার করে সংকলনের সময় একটি স্ট্রিংয়ের হ্যাশ গণনা করা সম্ভব হতে পারে। তবে, কেউই বেরিয়ে আসতে এবং এটি সম্ভব হবে বা এটি কীভাবে হবে তা বলার জন্য প্রস্তুত বলে মনে হয় না।

  • এটা কি সম্ভব?
  • অপারেটর দেখতে কেমন হবে?

আমি বিশেষত আগ্রহী এই জাতীয় ব্যবহারের ক্ষেত্রে।

void foo( const std::string& value )
{
   switch( std::hash(value) )
   {
      case "one"_hash: one(); break;
      case "two"_hash: two(); break;
      /*many more cases*/
      default: other(); break;
   }
}

দ্রষ্টব্য: কম্পাইল টাইম হ্যাশ ফাংশনটি ঠিক যেমনটি লিখেছি তেমন দেখতে হবে না। চূড়ান্ত সমাধানটি কেমন হবে তা অনুমান করার জন্য আমি যথাসাধ্য চেষ্টা করেছি তবে meta_hash<"string"_meta>::valueএটি একটি কার্যকর সমাধানও হতে পারে।


আমি তেমন কিছুই খুঁজে পাচ্ছি না, তবে আমি দেখতে পাচ্ছি যে আপনার হ্যাশিং ফাংশনটিকে একটি কনস্টেক্সপ্রেমে বাধ্য করা হয়েছে।
লুক

4
ইতিমধ্যে ব্যবহারকারী সংজ্ঞায়িত আক্ষরিক সমর্থন করে এমন একটি সংকলক রয়েছে কি? জিসিসি ( gcc.gnu.org/projects/cxx0x.html ) করে না এবং আমি ভিসি 10 এর জন্য তাদের উল্লেখ করাও পাইনি। সংকলক সমর্থন ব্যতীত এটি কেবল অনুমানের কাজ হতে পারে, তবে পরীক্ষিত ব্যবহারকারী-সংজ্ঞায়িত লিটারালগুলি দেখে মনে হচ্ছে এটি সম্ভব হওয়া উচিত।
জর্জিট ফ্রিটস্কে

4
এটি কিউট কিন্তু দরকারী না? যদি স্যুইচ মানটি রানটাইম স্ট্রিং হয় তবে আপনাকে সংঘর্ষের জন্যও পরীক্ষা করতে হবে। হতে পারে প্যাকিং আরও ভাল (আমার উত্তরে 9 টি অক্ষর 64 বিটে স্টাফ করার জন্য একটি প্যাক ফাংশন রয়েছে)।
u0b34a0f6ae

@ u0b34a0f6ae সংঘর্ষের জন্য কেন পরীক্ষা করবেন?
cubspl42

দুটি ক্ষেত্রে মান সমান হলে সংকলকটি একটি ত্রুটি জারি করা উচিত।
মার্ক স্টোরার

উত্তর:


90

এটি কিছুটা দেরি হয়ে গেছে, তবে আমি এর ব্যবহারের সাথে একটি সংকলন-সময় সিআরসি 32 ফাংশনটি বাস্তবায়নে সফল হয়েছি constexpr। এটির সাথে সমস্যাটি হ'ল লেখার সময়, এটি কেবল এমসিসিসি বা ইন্টেল সংকলক নয় বরং জিসিসির সাথে কাজ করে।

কোড স্নিপেট এখানে:

// CRC32 Table (zlib polynomial)
static constexpr uint32_t crc_table[256] = {
    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
    0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
    0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
...
};
template<size_t idx>
constexpr uint32_t crc32(const char * str)
{
    return (crc32<idx-1>(str) >> 8) ^ crc_table[(crc32<idx-1>(str) ^ str[idx]) & 0x000000FF];
}

// This is the stop-recursion function
template<>
constexpr uint32_t crc32<size_t(-1)>(const char * str)
{
    return 0xFFFFFFFF;
}

// This doesn't take into account the nul char
#define COMPILE_TIME_CRC32_STR(x) (crc32<sizeof(x) - 2>(x) ^ 0xFFFFFFFF)

enum TestEnum
{
    CrcVal01 = COMPILE_TIME_CRC32_STR("stack-overflow"),
};

CrcVal01 0x335CC04A এর সমান

আশা করি এটা তোমাকে সাহায্য করবে!


4
হ্যাঁ একেবারে. আমি এটি পাইথন সিআরসি 32 রানটাইম অ্যালগরিদমের (zlib থেকে আগত) বিরুদ্ধে পরীক্ষা করেছি এবং ফলাফলগুলি একই। আসলে, আপনি যা অর্জন করার চেষ্টা করছেন তা হ'ল কেন আমি এই কৌশলটি ব্যবহার করি!
ক্লিমেন্ট জ্যাকোবি

4
এটি পোস্ট করার জন্য ধন্যবাদ, এটি খুব দরকারী!
ট্যামস সেজেলি

4
আপনি একটি সংকলন পতাকা অনুপস্থিত ছিল। তবুও আমাকে স্টপ পুনরাবৃত্তি টেম্পলেট ফাংশনটিতে মান -1 মান দিতে হবে। আপডেট হওয়া সংস্করণটি এখানে পাওয়া যায় ( কলঙ্ক
ক্লিমেন্ট

4
constexprনভেম্বর ২০১৩ ছাড়া সিটিপি ব্লগস.এমএসএন

4
আপনি দুবার পুনরাবৃত্তি করছেন। স্ট্রিংয়ের দৈর্ঘ্যের ক্ষেত্রে এই দ্রবণটির একটি সূচকীয় জটিলতা রয়েছে, এবং সংকলক দ্বিতীয় কলটি যথেষ্ট পরিমাণে চালাক নয়। এই সমস্যার সম্ভাব্য সমাধানের জন্য অন্যান্য উত্তরগুলি পরীক্ষা করুন।
CygnusX1

30

কমপক্ষে আমার §7.1.5 / 3 এবং .15.19 পড়ার দ্বারা নিম্নলিখিতটি বৈধ হতে পারে:

unsigned constexpr const_hash(char const *input) {
    return *input ?
        static_cast<unsigned int>(*input) + 33 * const_hash(input + 1) :
        5381;
}

এটি rules7.1.5 / 3 এ প্রাথমিক বিধিগুলি অনুসরণ করে বলে মনে হচ্ছে:

  1. ফর্মটি হ'ল: "রিটার্ন এক্সপ্রেশন;"
  2. এর একমাত্র পরামিতিটি একটি পয়েন্টার, যা একটি স্কেলার প্রকার, এবং তাই আক্ষরিক প্রকার।
  3. এর রিটার্নটি স্বাক্ষরবিহীন ইনট, যা স্কেলার (এবং তাই আক্ষরিক)।
  4. রিটার্নের ধরণের কোনও অন্তর্নিহিত রূপান্তর নেই।

*inputএর মধ্যে একটি রূপান্তরকে মূল্যায়ন করার জন্য একটি অবৈধ লভ্যালু জড়িত কিনা তা নিয়ে কিছু প্রশ্ন রয়েছে এবং আমি নিশ্চিত নই যে আমি §5.19 / 2/6/2 1 এবং §4.1- এ নিয়মগুলি বুঝতে পেরেছি যে এটি সম্পর্কে নিশ্চিত হওয়া যথেষ্ট।

ব্যবহারিক দৃষ্টিকোণ থেকে, এই কোডটি g ++ দ্বারা গৃহীত হয়েছে, কমপক্ষে g ++ 4.7.1 হিসাবে ফিরে।

ব্যবহার এমন কিছু হবে:

switch(std::hash(value)) {
    case const_hash("one"): one(); break;
    case const_hash("two"): two(); break;
    // ...
    default: other(); break;
}

§5.19 / 2/6/2 এর প্রয়োজনীয়তা মেনে চলতে আপনাকে এই জাতীয় কিছু করতে হতে পারে:

// one of the `constexpr`s is probably redundant, but I haven't figure out which.
char constexpr * constexpr v_one = "one"; 

// ....

case const_hash(v_one): one(); break;
  1. আমি সংখ্যাহীন বুলেট পয়েন্টগুলি উল্লেখ করতে অতিরিক্ত 'স্ল্যাশ' নম্বর ব্যবহার করছি, সুতরাং the5.19 / 2 এর নীচে ষষ্ঠ বুলেট পয়েন্ট থাকলে এটি ভিতরে দ্বিতীয় বুলেট পয়েন্ট। আমি মনে করি পিট বেকারের সাথে এই জাতীয় অংশগুলি সনাক্ত করার জন্য অনুক্রমের নীচে কয়েকটি ধরণের সংখ্যা / অক্ষর / রোমান সংখ্যা যুক্ত করা সম্ভব কিনা সে সম্পর্কে আমার সাথে কথা বলতে হবে ...

4
এর সাথে দুটি জিনিস ভুল। 1: পুনরাবৃত্ত কলগুলিতে প্রবেশ করার অনুমতি নেই constexpr, 2: আপনার কোনও থামার অবস্থা নেই (যেখানে *input == nullptr) এবং আমি বুঝতে পারছি constexprআপনার কোনওটি থাকতে পারে না।
মোটি

9
এটি কোথায় বলে যে কনটেক্সপরে পুনরাবৃত্তি অনুমোদিত নয়? যতদূর আমি দেখতে পাচ্ছি, এটি কেবলমাত্র বলেছে যে আপনি যে কোনও ফাংশন কল করেন সেগুলি অবশ্যই কনটেক্সপ্রেট (§5.19 / 2/2) হিসাবে চিহ্নিত করা উচিত। আমি সমাপ্তির শর্তে একটি ভুল করেছি, যা আমি এখন ঠিক করেছি (আমি ঘটনাক্রমে ব্যবহার করেছি || যেখানে এটি হওয়া উচিত ছিল &&)।
জেরি কফিন

4
পুনরাবৃত্তিমূলক কনটেক্সপ্রে। আমি ২০০৮ সাল থেকে কিছু সভার মিনিট পড়েছি rec পুনরাবৃত্তিযোগ্য কনস্টেক্সট ফাংশনগুলিকে অনুমতি বা বাতিল করার বিষয়ে আলোচনা হয়েছিল। মূল বক্তব্যটি হ'ল বর্তমান শব্দটি এটি নিষেধ করেছিল না, এবং সামান্য এটি প্ররোচিত করেছে। কমিটি অনুভব করেছিল যে এরকম শক্তিশালী বৈশিষ্ট্যটি স্পষ্টভাবে বানানো উচিত। এটি ২০০৮ সালে ফিরে এসেছিল, আমি জানি না এরপরে কী ঘটেছিল।
deft_code

4
ডান - আমার সম্ভবত এটি উল্লেখ করা উচিত ছিল যে আমি এন 3000 থেকে যাচ্ছি, যা (আমি বিশ্বাস করি) বর্তমানে সর্বাধিক সাম্প্রতিক খসড়া। আমি নিশ্চিত যে এটি এক সময় নিষিদ্ধ ছিল, তবে কমপক্ষে আপাতত এটি অনুমোদিত হতে পারে বলে মনে হচ্ছে।
জেরি কফিন

4
উম, অ্যান্ড অ্যান্ড অপারেটর একটি বিল ফিরিয়ে দিচ্ছে, সুতরাং এই ফাংশনটি সম্ভবত আপনি যা চান তা করছে না। বিশেষত এটি খালি স্ট্রিংয়ের জন্য 0 প্রদান করে এবং সম্ভবত কিছু অন্যান্য স্ট্রিং শুরু হয় যা কোনও চর থেকে শুরু হয় (unsigned)-1; এবং অন্যান্য সমস্ত স্ট্রিংয়ের জন্য 1 প্রদান করে। টেরিনারি শর্তসাপেক্ষ অপারেটর দিয়ে আবার লিখুন?
ndkrempel

14

এটি ওপির সমস্যাটি যথাসম্ভব সমাধানের চেষ্টা an

namespace my_hash {
  template<class>struct hasher;
  template<>
  struct hasher<std::string> {
    std::size_t constexpr operator()(char const *input)const {
      return *input ?
        static_cast<unsigned int>(*input) + 33 * (*this)(input + 1) :
        5381;
    }
    std::size_t operator()( const std::string& str ) const {
      return (*this)(str.c_str());
    }
  };
  template<typename T>
  std::size_t constexpr hash(T&& t) {
    return hasher< typename std::decay<T>::type >()(std::forward<T>(t));
  }
  inline namespace literals {
    std::size_t constexpr operator "" _hash(const char* s,size_t) {
      return hasher<std::string>()(s);
    }
  }
}
using namespace my_hash::literals;
void one() {} void two() {} void other() {}

void foo( const std::string& value )
{
  switch( my_hash::hash(value) )
  {
    case "one"_hash: one(); break;
    case "two"_hash: two(); break;
    /*many more cases*/
    default: other(); break;
  }
}

সরাসরি উদাহরণ

মূল পার্থক্যটি দ্রষ্টব্য - std::hashব্যবহার করা যাবে না, কারণ আমাদের std::hashঅ্যালগোরিদমের উপর আমাদের নিয়ন্ত্রণ নেই এবং সংকলনের সময় এটি মূল্যায়নের জন্য আমাদের অবশ্যই এটি পুনরায় সংশোধন করতে হবেconstexpr । এছাড়াও, কোনও "স্বচ্ছ" হ্যাশ নেই std, সুতরাং আপনি (একটি তৈরি না করে std::string) একটি কাঁচা চরিত্রের বাফার হিসাবে হ্যাশ করতে পারবেন নাstd::string

আমি std::stringকাস্টম হ্যাশার (স্বচ্ছ const char*সমর্থন সহ) একটি my_hashনেমস্পেসে আটকেছি , যাতে আপনি এটি একটিতে সঞ্চয় করতে পারেনstd::unordered_map ধারাবাহিকতার প্রয়োজন হয় তবে আপনি ।

@ জেরি কফিনের দুর্দান্ত উত্তর এবং এর নীচে মন্তব্য থ্রেডের ভিত্তিতে, তবে এটি বর্তমান সি ++ 11 সেরা অনুশীলন (তাদের প্রত্যাশার বিপরীতে!) দিয়ে লেখার প্রয়াস দিয়ে।

নোট করুন যে একটি switchবিবৃতিতে "কাঁচা হ্যাশ" ব্যবহার caseকরা বিপজ্জনক। আপনি একটি করতে চাইবেন==এটি কাজ করেছে তা নিশ্চিত করার জন্য আপনি পরে তুলনা ।


4
লাইভ উদাহরণ লিঙ্কটি ভুল / পুরানো বলে মনে হচ্ছে?
fuenfundachtzig

@ ফুয়েনফান্ডাচটজিগ আপনি কি বিশ্বাস করবেন যে আমি ঠিক এটি স্থির করেছি?
ইয়াক্ক - অ্যাডাম নেভ্রামাউন্ট

13

এই স্নিপেটটি ক্লিমেন্ট জ্যাকোবি-র একটিতে ভিত্তিক। তবে ঝাঁকুনির সাথেও কাজ করে। এবং এটি সংকলনে দ্রুত হওয়া উচিত (এটির মধ্যে কেবল একটি পুনরাবৃত্ত কল রয়েছে, মূল পোস্টে দুটি নয়)।

#include <iostream>
#include <string>
#include <vector>

static constexpr unsigned int crc_table[256] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    0xe963a535, 0x9e6495a3,    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};


template<int size, int idx = 0, class dummy = void>
struct MM{
  static constexpr unsigned int crc32(const char * str, unsigned int prev_crc = 0xFFFFFFFF)
  {
      return MM<size, idx+1>::crc32(str, (prev_crc >> 8) ^ crc_table[(prev_crc ^ str[idx]) & 0xFF] );
  }
};

// This is the stop-recursion function
template<int size, class dummy>
struct MM<size, size, dummy>{
  static constexpr unsigned int crc32(const char * str, unsigned int prev_crc = 0xFFFFFFFF)
  {
      return prev_crc^ 0xFFFFFFFF;
  }
};

// This don't take into account the nul char
#define COMPILE_TIME_CRC32_STR(x) (MM<sizeof(x)-1>::crc32(x))


template<unsigned int crc>
void PrintCrc()
{
    std::cout << crc << std::endl;
}


int main()
{

    PrintCrc<COMPILE_TIME_CRC32_STR("HAH")>();
}

ধারণা ধারণা এখানে দেখুন


4
আপনাকে ধন্যবাদ, জ্যাকব এর উত্তর আমি জিসিসিতে যা চেয়েছিলাম তার জন্য ঠিক কাজ করেছে তবে এমএসভিসি আরও বড় স্ট্রিং সহ ত্রুটি ছুঁড়েছিল। আপনার উত্তরটি আমার বড় বড় স্ট্রিংগুলির সাথে এমএসভিসি তে কাজ করে যা হ্যাশ করা দরকার।
ড্যানিয়েল মুডি

8

নোট করুন যে এখানে প্রদর্শিত ফর্মটি মান হিসাবে গ্রহণ করা হয়নি, নীচে উল্লিখিত হিসাবে।

সংকলন টাইম স্ট্রিং প্রসেসিং N2765 এর প্রস্তাবিত ব্যবহারকারী-সংজ্ঞায়িত আক্ষরিক মাধ্যমে সম্ভব হয়ে উঠবে বলে অনুমান করা হয় ।
আমি ইতিমধ্যে উল্লিখিত হিসাবে, আমি বর্তমানে এটি প্রয়োগ করে এমন কোনও সংকলক সম্পর্কে জানি না এবং সংকলক সমর্থন ব্যতীত কেবল অনুমানের কাজ থাকতে পারে।

Draft2.13.7.3 এবং 4 খসড়াটির মধ্যে আমাদের নিম্নলিখিত রয়েছে:

অন্যথায় (এসটিতে একটি আক্ষরিক অপারেটর টেম্পলেট রয়েছে), এল ফর্ম
অপারেটরের "" X <'c1', 'c2', ..., 'ck'> () এর কল হিসাবে বিবেচিত হবে যেখানে এন উত্স অক্ষরের ক্রম c1c2 ... সিকে [দ্রষ্টব্য: সিকোয়েন্স সি 1 সি 2 ... সিকে কেবলমাত্র মূল উত্স অক্ষর সেট থেকে অক্ষর থাকতে পারে। অন্তর্ভুক্ত নোট]

এর সাথে একত্রিত করুন constexprএবং আমাদের সংকলন টাইম স্ট্রিং প্রসেসিং করা উচিত।

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

যে হচ্ছে বললেন, সি ++ 0x আমার সীমিত আভাস সঙ্গে, এটা হতে পারে ভালো কিছু (ঝ সম্ভবত কিছু ভুল পেয়েছিলাম) চেহারা:

template<char c, char... str>
struct hash {
    static const unsigned result = c + hash<str...>::result;
};

template<char c>
struct hash {
    static const unsigned result = c;
};

template<char... str> 
constexpr unsigned
operator "" _hash() {
    return hash<str>::result;
}

// update: probably wrong, because the above 
// form is not allowed for string-literals:    
const unsigned h = "abcd"_hash;

যদি জেরিসের পদ্ধতির কাজ হয় তবে নিম্নলিখিতগুলির সাথে তবে কাজ করা উচিত:

constexpr unsigned operator "" _hash(const char* s, size_t) {
    return const_hash(s);
}

ভের দৈর্ঘ্যের টেম্পলেট এবং constexprব্যবহারকারীর সংজ্ঞায়িত আক্ষরিকের দুর্দান্ত (এবং প্রয়োজনীয়) সংমিশ্রণ । আমি নিশ্চিত নন যে আপনি টেম্পলেট প্যারামিটার হিসাবে স্ট্রিং আক্ষরিক ব্যবহার করতে পারেন, তাদের স্থির যোগসূত্র নেই? (তারা কমপক্ষে সি ++ 98 এ করে এবং তাই টেম্পলেট প্যারামিটার হিসাবে ভার্বোটেন)।
মোটি

আমি অনুচ্ছেদগুলি মিশ্রিত করেছি এবং ভেবেছিলাম যে এই মামলাটি একটি ব্যতিক্রম ছিল - দুঃখজনকভাবে এটি এমনটি বলে মনে হয় না।
জর্জিট ফ্রিটস্কে

4
@ মট্টি: জিএফ স্ট্রিং আক্ষরিক টেম্পলেট প্যারামিটার হিসাবে কোথায় ব্যবহার করছে? আপনি কি অক্ষরের আক্ষরিক হিসাবে অক্ষরের বৈকল্পিক টেম্পলেটটি বিভ্রান্ত করছেন?
deft_code

আসল প্রস্তাবনা থেকে মনে হচ্ছে, স্ট্রিং লিটারালগুলির জন্য টেমপ্লেট সংস্করণটি গৃহীত হয়নি ( কনট্যাক্টেশন ইস্যুগুলির কারণে? Stackoverflow.com/questions/1108008/any-ideas-for-c1y/… - মন্তব্য) - খুব খারাপ।
জর্জিট ফ্রিটস্কে

4
operator ""_hashএক্সকোড 5.0.2 এ আমার জন্য কাজ করা শেষ সংস্করণ ।
cubspl42

8

ক্লিমেন্ট জ্যাকোবি'র একের ভিত্তিতে আর একটি সমাধান, সি ++ 11 কনস্টেক্সপ্র ব্যবহার করে (বর্ধিত সি ++ 14 নয়) তবে কেবল একটি পুনরাবৃত্তি রয়েছে।

namespace detail {
// CRC32 Table (zlib polynomial)
static constexpr uint32_t crc_table[256] = { 0x00000000L, 0x77073096L, ... }

template<size_t idx>
constexpr uint32_t combine_crc32(const char * str, uint32_t part) {
  return (part >> 8) ^ crc_table[(part ^ str[idx]) & 0x000000FF];
}

template<size_t idx>
constexpr uint32_t crc32(const char * str) {
  return combine_crc32<idx>(str, crc32<idx - 1>(str));
}

// This is the stop-recursion function
template<>
constexpr uint32_t crc32<size_t(-1)>(const char * str) {
  return 0xFFFFFFFF;
}

} //namespace detail

template <size_t len>
constexpr uint32_t ctcrc32(const char (&str)[len]) {
  return detail::crc32<len - 2>(str) ^ 0xFFFFFFFF;
}

কিছু ব্যাখ্যা

  • আমরা একটি একক পুনরাবৃত্তি ব্যবহার করছি, যাতে ফাংশনটি আরও দীর্ঘ স্ট্রিংয়ের জন্যও ভালভাবে কাজ করে।
  • অতিরিক্ত ফাংশন combine_crc32আমাদের একটি চলকের অধীনে পুনরাবৃত্তির ফলাফল সংরক্ষণ করতে দেয়part এবং এটি দুবার ব্যবহার করার অনুমতি দেয়। এই ফাংশনটি C ++ 11 সীমাবদ্ধতার জন্য স্থানীয় ভেরিয়েবল ঘোষণাকে অস্বীকার করার জন্য একটি ওয়াকাকারআউন্ড।
  • ctcrc32ফাংশন একটি স্ট্রিং আক্ষরিক, যা একটি হিসাবে পাস করা হয়েছে আশা const char (&)[len]। এইভাবে আমরা টেমপ্লেট প্যারামিটার হিসাবে স্ট্রিংয়ের দৈর্ঘ্য পেতে পারি এবং ম্যাক্রোর উপর নির্ভর করতে হবে না।

4
এটি আমার প্রিয় বাস্তবায়ন হিসাবে শেষ হয়েছে, আপনাকে ধন্যবাদ।
ড্যানিয়েল মুডি

6

নিম্নলিখিতটি জিসিসি 4.6.1 এ কাজ করে এবং আপনি hashবা packসুইচ ব্লকগুলি ব্যবহার করতে পারেন ।

/* Fast simple string hash (Bernstein?) */                                       
constexpr unsigned int hash(const char *s, int off = 0) {                        
    return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];                           
}                                                                                

/* Pack the string into an unsigned int                                          
 * Using 7 bits (ascii) it packs 9 chars into a uint64_t                         
 */                                                                              
template <class T = uint64_t, unsigned int Bits = 7>                             
constexpr T pack(const char *s, unsigned int off = 0) {                          
    return (Bits*off >= CHAR_BIT*sizeof(T) || !s[off]) ? 0 :                     
        (((T)s[off] << (Bits*off)) | pack(s,off+1));                             
}  

জিসিসি আপাতদৃষ্টিতে (?) পুনরাবৃত্ত কলগুলিকে মঞ্জুরি দেয় না যেখানে আমরা পয়েন্টার s+1সহ প্রেরণ করি s, তাই আমি offভেরিয়েবলটি ব্যবহার করি ।


5

আপনার যদি একটি সি ++ 17 সংকলক এবং স্ট্রিং_ভিউ থাকে তবে এটি তুচ্ছ হয়ে ওঠে, কেবলমাত্র সাধারণ সংস্করণটি লিখুন:

constexpr uint32_t crc32(std::string_view str)
{
    uint32_t crc = 0xffffffff;
    for (auto c : str)
        crc = (crc >> 8) ^ crc_table[(crc ^ c) & 0xff];
    return crc ^ 0xffffffff;
}

নোট করুন যে সংকলক আপনি কেবল লিখলে crc32("mystring")(সাধারণত ভিএস তা করতে থাকে) সংকলনের সময় এটি প্রক্রিয়া না করার সিদ্ধান্ত নিতে পারে । সমস্যাটি সমাধান করার কৌশলটি হ'ল একটি ক্রিয়াকলাপ পরিবর্তনশীল তৈরি করা যা আপনার crc32 এর সংকলনের সময় মূল্যায়নের উপর নির্ভর করে। সাধারণতconstexpr uint32_t val = crc32("mystring");
গিলাইম গ্রিস

3

এখানে আরও একটি সি ++ 11 বাস্তবায়ন রয়েছে (@ সাইগনএক্সএক্স 1 উত্তরের উপর ভিত্তি করে), যা উভয় কনস্টেক্সপ্র চর চর এবং রানটাইম স্ট্রিংয়ের সাথে কাজ করে:

namespace detail {

    // CRC32 Table (zlib polynomial)
    static constexpr uint32_t crc_table[256] = { 0x00000000L, 0x77073096L, ... };

    constexpr uint32_t combine_crc32(size_t idx, const char * str, uint32_t part) {
        return (part >> 8) ^ crc_table[(part ^ str[idx]) & 0x000000FF];
    }

    constexpr uint32_t crc32(size_t idx, const char * str) {
        return idx == size_t(-1) ? 
            0xFFFFFFFF : combine_crc32(idx, str, crc32(idx - 1, str));
    }
}

uint32_t ctcrc32(std::string const& str) {
    size_t len = str.size() + 1;
    return detail::crc32(len - 2, str.c_str()) ^ 0xFFFFFFFF;
}

template <size_t len>
constexpr uint32_t ctcrc32(const char (&str)[len]) {
    return detail::crc32(len - 2, str) ^ 0xFFFFFFFF;
}

আপনার প্রয়োজন str.size() + 1কারণ lenদ্বিতীয় ওভারলোড strlen(str) + 1শেষে নাল-চরিত্রের কারণে।

আমি const char *এটির জন্য কোনও ওভারলোড যুক্ত করিনি কারণ এটি দ্বিতীয় ওভারলোডের সাথে মিশে যায় - আপনি সহজেই const char *, size_tবা এর জন্য ওভারলোডগুলি যোগ করতে পারেন std::string_view


2

এটি একটি দুর্দান্ত প্রশ্ন।

জেরি কফিনের উত্তরের ভিত্তিতে, আমি আরও একটি তৈরি করেছি যা ভিজ্যুয়াল স্টুডিও 2017 এর স্ট্যান্ড :: হ্যাশের সাথে সামঞ্জস্যপূর্ণ।

#include <functional>
#include <cassert>
using namespace std;


constexpr size_t cx_hash(const char* input) {
    size_t hash = sizeof(size_t) == 8 ? 0xcbf29ce484222325 : 0x811c9dc5;
    const size_t prime = sizeof(size_t) == 8 ? 0x00000100000001b3 : 0x01000193;

    while (*input) {
        hash ^= static_cast<size_t>(*input);
        hash *= prime;
        ++input;
    }

    return hash;
}


int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */

    auto a = cx_hash("test");
    hash<string> func;
    auto b = func("test");
    assert(a == b);

    return 0;
}

https://github.com/manuelgustavo/cx_hash


0

আমি এখনও একটি crc32- আক্ষরিক বৈকল্পিক (যা টেমপ্লেটগুলি দিয়ে সম্ভব নয়) অনুপস্থিত ছিল, তাই এখানে CygnusX1 এর উপর ভিত্তি করে আমার পরামর্শটি দেওয়া হল । কিছু পরীক্ষা করেছেন, প্রতিক্রিয়া জানাতে নির্দ্বিধায়।

এমএসভিসিতে টেস্টেট।

PS: আমি অন্য কোথাও অতিরিক্ত জিনিস অনুসন্ধান করা ঘৃণা করি, তাই আমি আমার উত্তরের নীচে সিআরসি টেবিলটি অনুলিপি করেছি।

#include <inttypes.h>

namespace detail
{
    // CRC32 Table (zlib polynomial)
    static constexpr uint32_t crc_table[256] =
    {
        0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
        ...
    };

    constexpr uint32_t combine_crc32( const char c, uint32_t part )
    {
        return (part >> 8) ^ crc_table[(part ^ c) & 0x000000FF];
    }

    constexpr uint32_t crc32( const char * str, size_t idx )
    {
        return combine_crc32( str[idx], idx ? crc32( str, idx - 1 ) : 0xFFFFFFFF );
    }
} //namespace detail

constexpr uint32_t ctcrc32( const char* str, size_t len )
{
    return detail::crc32( str, len ) ^ 0xFFFFFFFF;
}

size_t constexpr operator "" _hash( const char* str, size_t len )
{
    return ctcrc32( str, len );
}

ড্যান বার্নস্টেইন (ডিজেবি 2) এর অ্যালগরিদমনের সাথে বিকল্প ( জেরি কফিন + জর্জ ফ্রিটস্কের সম্মিলিত উত্তর )

unsigned constexpr const_hash( char const *input )
{
    return *input ?
        static_cast<unsigned int>(*input) + 33 * const_hash( input + 1 ) :
        5381;
}
size_t constexpr operator "" _hash( const char* str, size_t len )
{
    return const_hash( str );
}

Crc32 টেবিল:

static constexpr uint32_t crc_table[256] =
    {
        0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
        0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
        0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
        0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
        0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
        0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
        0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
        0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
        0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
        0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
        0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
        0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
        0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
        0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
        0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
        0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
        0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
        0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
        0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
        0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
        0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
        0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
        0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
        0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
        0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
        0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
        0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
        0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
        0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
        0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
        0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
        0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
        0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
        0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
        0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
        0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
        0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
        0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
        0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
        0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
        0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
        0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
        0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
        0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
        0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
        0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
        0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
        0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
        0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
        0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
        0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
        0x2d02ef8dL
    };
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.