Необходимо было указать верхний предел при оценке длины строки C-стиля посредством метапрограммирования шаблонов

52
7

Недавно я начал играть с метапрограммированием шаблонов в C++ и пытался оценить длину строки в стиле C.

У меня был некоторый успех с этим битом кода

template <const char *str, std::size_t index>
class str_length {
public:
static inline std::size_t val() {
return (str[index] != '\0') ? (1 + str_length<str, index + 1>::val()) : 0;
}
};

template <const char *str>
class str_length <str, 500> {
public:
static inline std::size_t val() {
return 0;
}
};

extern const char bitarr[] { "0000000000000000000" };

int main() {
std::cout << str_length<bitarr, 0>::val() << std::endl;

getchar();
return 0;
}

Однако мне пришлось установить "верхний предел" 500 путем создания специализации str_length. Опущение, которое заставит мой компилятор работать неограниченно (предположительно создавая бесконечные специализации str_length).

Есть ли что-нибудь, что я мог бы сделать, чтобы не указывать лимит index = 500? Я использую V C++ 2015, если это поможет.

О, и я не использую constexpr, потому что V C++ не совсем поддерживает расширенные функции C++ 14 constexpr. (https://msdn.microsoft.com/en-us/library/hh567368.aspx#cpp14table)

спросил(а) 2016-08-01T05:13:00+03:00 3 года, 8 месяцев назад
1
Решение
112

Обычный способ остановить создание бесконечного шаблона в этой ситуации - это использование специализации; который ортогонален constexpr -ness чего угодно. Просмотрев список дополнительных материалов, которые расширил возможности constexpr в С++ 14, я не вижу ничего в следующем примере, который требует расширенной поддержки constexpr. gcc 6.1.1 компилирует это в режиме соблюдения -std=c++11, FWIW:

#include <iostream>

template<const char *str, size_t index, char c> class str_length_helper;

template <const char *str>
class str_length {
public:

static constexpr std::size_t val()
{
return str_length_helper<str, 0, str[0]>::val();
}
};

template<const char *str, std::size_t index, char c>
class str_length_helper {

public:

static constexpr std::size_t val()
{
return 1+str_length_helper<str, index+1, str[index+1]>::val();
}
};

template<const char *str, std::size_t index>
class str_length_helper<str, index, 0> {
public:

static constexpr std::size_t val()
{
return 0;
}
};

static constexpr char bitarr[] { "0000000000000000000" };

int main() {
std::cout << str_length<bitarr>::val() << std::endl;

getchar();
return 0;
}

Обратите внимание, однако, что сама строка символов должна быть constexpr. Как отмечалось в комментариях, это имеет сомнительное практическое применение; но нет ничего плохого в том, чтобы вступить в дело таким образом, чтобы повесить метапрограммирование.

Ключевым моментом является использование специализации и тот факт, что для того, чтобы использовать str[index] в качестве параметра шаблона, str должна быть constexpr.

ответил(а) 2016-08-01T05:40:00+03:00 3 года, 8 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема