Вот смотрите. Я оставил практически полностью Ваш код, но изменил функцию подсчёта длины (про неё позже).
Также я добавил макрос WITH_CALC
(первая строка). Если указать там true
, то компилируется Ваш вариант, а если false
– то такая же структура но безо всяких вычислений с голимыми константами. Это было сделано для проверки. Теперь Вы можете скомпилировать c true
и с false
и сравнить размер кода и данных. Как видите, размеры идентичны. Это доказывает, что все вычисления были сделаны компилятором, а в код попали только готовые константы.
Теперь про функцию подсчёта длины.
- она не использует никакие поля структуры (и не может, т.к. Вы её вызываете до создания экземпляра). Значит, она просто просится быть
static
. - Вы вызываете её в
constexpr
-конструкторе, значит она обязана бытьconstexpr
- В С++11 (а “искаропки” указан именно он) тело
constexpr
-функции обязано состоять из единственного оператораreturn
, поэтому я переписал её соответствующим образом (кстати, я не проверял Ваш вариант на корректность, просто переписал один в один)
Собственно, всё. Смотрите, разбирайтесь
#define WITH_CALC true
#if WITH_CALC /////////////////////////////////////////////////////////////////////
struct SExample {
// конструктор, рассчитываем на этапе компиляции
constexpr SExample(const char* const str) : _str(str), _len_utf8(strlenUtf8(str)) {}
// длина строки в UTF-8
static constexpr size_t strlenUtf8(const char *ptr /* const s*/) {
return ! * ptr ? 0 : ((((*ptr & 0xc0) != 0x80) ? 1 : 0) + strlenUtf8(ptr + 1));
}
size_t length(void) const { return _len_utf8; }
protected:
const char* const _str;
const size_t _len_utf8;
};
SExample ex = SExample("Пример");
#else /////////////////////////////////////////////////////////////////////
struct SExample {
size_t length(void) const { return _len_utf8; }
const char* const _str;
const size_t _len_utf8;
};
SExample ex = (SExample) { "Привет", 6 };
#endif /////////////////////////////////////////////////////////////////////
void setup(void) {
Serial.begin(115200);
Serial.print(ex.length());
}
void loop(void) {}