Статическая таблица внутри функции constexpr - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть этот кусок сгенерированного кода, который отображает целые числа в целые, ядро ​​которых представляет собой простую таблицу.В до C ++ 17 это выглядело так:

int convert (int v)
{
  static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };

  if (0 <= v && v < sizeof table / sizeof table[0])
    return table[v];
  else
    return -1;
}

с C ++ 17, я хотел бы использовать constexpr.Я ожидал, что добавления constexpr к сигнатуре функции будет достаточно, но мне нужно удалить static таблицы, что делает мою реализацию более сложной, по-видимому, без веской причины.Не стоит также упоминать, что table в контексте non constexpr, вероятно, будет в стеке, поэтому, я думаю, мне следует заменить static на constexpr.

G ++ 8 отчетов:

/tmp/foo.cc: In function 'constexpr int convert(int)':
/tmp/foo.cc:14:26: error: 'table' declared 'static' in 'constexpr' function
   static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
                          ^

и Clang ++ 7:

/tmp/foo.cc:14:20: error: static variable not permitted in a constexpr function
  static const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };
                   ^
1 error generated.

Поскольку я хочу, чтобы этот фрагмент кода работал со всеми стандартами C ++ (и делал правильные вещи в каждом случае), я думаю, что долженнапишите это (да, макросы, это не вопрос):

#if 201703L <= __cplusplus
# define CONSTEXPR constexpr
# define STATIC_ASSERT static_assert
# define STATIC_OR_CONSTEXPR constexpr
#else
# include <cassert>
# define CONSTEXPR
# define STATIC_ASSERT assert
# define STATIC_OR_CONSTEXPR static
#endif

CONSTEXPR int convert (int v)
{
  STATIC_OR_CONSTEXPR const int table[] = { 3, 2, 6, 1, 7, 1, 6, 8 };

  if (0 <= v && v < sizeof table / sizeof table[0])
    return table[v];
  else
    return -1;
}

int main()
{
  STATIC_ASSERT(convert(-42) == -1);
  STATIC_ASSERT(convert(2) == 6);
  STATIC_ASSERT(convert(7) == 8);
  STATIC_ASSERT(convert(8) == -1);
}

Итак:

  • что мотивирует запрет иметь статические переменные хранения в функциях constexpr?

  • есть ли более чистая альтернатива, которую я мог пропустить?Конечно, я могу извлечь table из convert, но я бы хотел этого избежать.

  • обеспечивает стандартную гарантию того, что константные массивы в функциях constexpr в контекстах не-constexpr будутбыть в статическом хранилище вместо стека?

1 Ответ

0 голосов
/ 27 декабря 2018
  • Есть ли более чистая альтернатива, которую я мог пропустить?Конечно, я могу вытащить таблицу из конвертирования, но я бы хотел этого избежать.

Как насчет (C ++ 11 совместимый):

template <int... Ns>
struct MyTable
{
    static constexpr int get(std::size_t v)
    {
        return v < sizeof...(Ns) ? data[v] : -1;
    }

    static constexpr int data[] = {Ns...};  
};

constexpr int convert (std::size_t v)
{
    using table = MyTable<3, 2, 6, 1, 7, 1, 6, 8>;

    return table::get(v);
}

Демо

  • гарантирует ли стандартная гарантия, что массивы const в функциях constexpr в контекстах non-constexpr будут находиться в статическом хранилище вместо стека?

Я не думаю, что переменная constexpr должна быть материализована, превращение этого кода в switch (или идеальный хеш) кажется верной реализацией.

Так что никакой гарантии, я думаю.

...