Как создать boost::hana::map с ключами, являющимися строками времени компиляции (C++14)?

Я видел в списке рассылки boost.hana следующий пример, который не компилируется:

#include <boost/hana.hpp>
#include <string>
namespace hana = boost::hana;
int main(int argc, char **argv) {

    constexpr auto m1 = hana::make_map(
            hana::make_pair("key1"_s, hana::type_c<std::string>),
            hana::make_pair("key2"_s, hana::type_c<std::string>)
        ); 
}

Я получаю следующую ошибку в GCC 7.3.0 -std=c++14:

error: unable to find string literal operator ‘operator""_s’ with ‘const char [5]’, ‘long unsigned int’ arguments
             hana::make_pair("key1"_s, hana::type_c<std::string>),
                             ^~~~~~~~

И, кстати, что за суффикс «_s» у строкового литерала?


person Adam Ryczkowski    schedule 10.07.2018    source источник


Ответы (2)


Оператор строкового литерала времени компиляции, который использует Boost.Hana _s, представляет собой gcc и должно быть включено путем определения BOOST_HANA_CONFIG_ENABLE_STRING_UDL.

Вы также должны импортировать оператор в текущее пространство имен из boost::hana::literals.

В качестве альтернативы можно использовать макрос BOOST_HANA_STRING, но он использует lambda и не может быть constexpr в C++14.

Хотя это и не завершено, С++ 20, вероятно, будет иметь этот оператор, а также строковые литералы в качестве параметров шаблона, что интересно. (здесь)

Вот полный пример:

#define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
#include <boost/hana.hpp>

namespace hana = boost::hana;
using namespace hana::literals;

int main() {
  constexpr auto m1 = hana::make_map(
    hana::make_pair("key1"_s, hana::type_c<void>),
    hana::make_pair("key2"_s, hana::type_c<void>)
  );

  constexpr auto m3 = hana::make_map(
    hana::make_pair(hana::string<'k','e','y','1'>{}, hana::type_c<void>),
    hana::make_pair(hana::string<'k','e','y','2'>{}, hana::type_c<void>)
  );

  // not constexpr until C++17
  auto m2 = hana::make_map(
    hana::make_pair(BOOST_HANA_STRING("key1"), hana::type_c<void>),
    hana::make_pair(BOOST_HANA_STRING("key2"), hana::type_c<void>)
  );
}
person Jason Rice    schedule 10.07.2018

Причина не компилируется на самом деле суффикс «_s». Решение: скомпилировать с -DBOOST_HANA_CONFIG_ENABLE_STRING_UDL.

В качестве альтернативы используйте hana::string_c<'k', 'e', 'y', '1'> вместо "key1"_s и hana::string_c<'k', 'e', 'y', '2'> вместо "key2"_s)

Объяснение

Этот суффикс представляет собой интерпретацию Hana нестандартного расширения C++ под названием «шаблон оператора строкового литерала». Он доступен только в компиляторах GCC и Clang, поэтому его поддержка Hana по умолчанию отключена.

Это расширение не вошло в стандарт (после нескольких попыток), потому что оно создает строковые типы наименее эффективным способом - посимвольно. Включение его в стандарт будет стимулировать его использование, что приведет к значительному увеличению времени компиляции.

Других альтернатив нет, за исключением, может быть, трюка, используемого boost::mpl::string, который использует 4-байтовые символьные литералы Unicode вместо однобайтовых символьных литералов, что должно сократить время компиляции на четыре (но тогда вы ограничены строками ASCII).

person Adam Ryczkowski    schedule 10.07.2018