Автор пытается помочь вам избежать случайных проблем с производительностью, которые возникают при повторном хешировании строк. Поскольку хеширование строк стоит дорого, вы, вероятно, захотите сделать это один раз и кэшировать его где-нибудь. Если у них есть неявный конструктор, вы можете неоднократно хэшировать одну и ту же строку, не зная или не намереваясь сделать это.
Таким образом, библиотека предоставляет неявную конструкцию для строковых литералов, которая может быть вычислена во время компиляции с помощью constexpr
, но явная конструкция для const char*
в целом, поскольку они могут ' Обычно это делается во время компиляции, и вы хотите избежать повторения или случайного повторения.
Рассмотрим:
void consume( hashed_string );
int main()
{
const char* const s = "abc";
const auto hs1 = hashed_string{"my.png"}; // Ok - explicit, compile-time hashing
const auto hs2 = hashed_string{s}; // Ok - explicit, runtime hashing
consume( hs1 ); // Ok - cached value - no hashing required
consume( hs2 ); // Ok - cached value - no hashing required
consume( "my.png" ); // Ok - implicit, compile-time hashing
consume( s ); // Error! Implicit, runtime hashing disallowed!
// Potential hidden inefficiency, so library disallows it.
}
Если я удалю последнюю строку, вы увидите, как компилятор применяет для вас неявные преобразования в C ++ Insights :
consume(hashed_string(hs1));
consume(hashed_string(hs2));
consume(hashed_string("my.png"));
Но он отказывается сделать это для строки consume(s)
из-за неявных / явных конструкторов.
Обратите внимание, однако, что эта попытка защитить пользователя не является надежной. Если вы объявите вашу строку как массив, а не как указатель, вы можете случайно повторно хэшировать:
const char s[100] = "abc";
consume( s ); // Compiles BUT it's doing implicit, runtime hashing. Doh.
// Decay 's' back to a pointer, and the library's guardrails return
const auto consume_decayed = []( const char* str ) { consume( str ); }
consume_decayed( s ); // Error! Implicit, runtime hashing disallowed!
Этот случай встречается реже, и такие массивы обычно распадаются на указатели, когда они передаются другим функциям, которые затем будут вести себя как выше. Библиотека может обеспечить принудительное хеширование во время компиляции для строковых литералов с if constexpr
и т.п. и запретить его для не-литеральных массивов, таких как s
выше. (Есть ваш запрос на возврат в библиотеку!) [См. Комментарии.]
Чтобы ответить на ваш последний вопрос: причины для этого должны быть более быстрыми для контейнеров на основе хеша, таких как std::unordered_map
. Он минимизирует количество хэшей, которые вы должны сделать, вычисляя хэш один раз и кэшируя его внутри hashed_string
. Теперь при поиске ключей на карте нужно просто сравнить предварительно вычисленные значения хеш-ключей для ключей и строку поиска.