constexpr конструктор и функции

Имам този клас encrypted_string, който трябва да шифрова низове по време на компилация. Проблемът, който имам, е, че не мога да извикам членската функция „encrypt“ в конструктора, но ако поставя криптирането в самия конструктор, то работи.

template<typename I>
class encrypted_string;

template<size_t... I>
class encrypted_string<std::index_sequence<I...>>
{
 private:
  std::array<char, sizeof...(I)> buf;

  constexpr char encrypt(char c) const { return c ^ 0x41; }

 public:
  constexpr encrypted_string(const char* str)
  : buf { (str[I] ^ 0x41)... } { } // Works
  //: buf { this->encrypt(str[I])... } { } // Error
};

#define enc(str) encrypted_string<std::make_index_sequence<sizeof(str)>>(str)

int main()
{
  // Ensures compile time evaluation
  constexpr auto s = enc("Test");

  return 0;
}

Компилирам с 'g++ encrypted_string.cpp -std=c++14 -o encrypted_string' и моята gcc версия е 4.9.2.

Грешката, която получавам, не ми казва много:

encrypted_string.cpp:17:13: note: ‘constexpr encrypted_string<std::integer_sequence<long unsigned int, _Idx ...> >::encrypted_string(const char*) [with long unsigned int ...I = {0ul, 1ul, 2ul, 3ul, 4ul}]’ is not usable as a constexpr function because:
constexpr encrypted_string(const char* str) : buf { this->encrypt(str[I])... } { }

Правя ли нещо нередно или просто не е възможно да извикам функции constexpr в конструктора constexpr? От това, което разбрах за конструкторите constexpr, би трябвало да е възможно.


person Freszone    schedule 27.06.2015    source източник
comment
constexpr се оценява по време на компилиране, така че предполагам, че извикването на методи, които са част от екземпляр на клас, не е правилно валидна заявка. Не съм сигурен в това, но има смисъл поне за мен.   -  person skypjack    schedule 27.06.2015
comment
Работи добре в gcc 5.1   -  person user657267    schedule 27.06.2015
comment
Облекчените константни изрази на C++14 са внедрени в gcc ›= 5, вижте gcc.gnu.org /projects/cxx1y.html С правилата на C++11 може да няма никакъв код в тялото на конструктора (само typedefs, статични твърдения и т.н., без потенциален код по време на изпълнение).   -  person dyp    schedule 27.06.2015
comment
Направете функция член static или не член.   -  person Tomilov Anatoliy    schedule 27.06.2015
comment
Благодаря ви за отговорите, успях да го компилирам на gcc 4.9, като промених функцията за шифроване на staticкакто Orient посочи. Актуализирах до gcc 5.1 и сега работи, както очаквах, без никакви модификации.   -  person Freszone    schedule 28.06.2015


Отговори (1)


Според https://gcc.gnu.org/projects/cxx1y.html, C Поддръжката на ++14 constexpr не се прилага до GCC 5.

В резултат на това GCC 4.9.2, дори и с -std=c++14, поддържа само C++11 constexprs, които съдържат един оператор, който произвежда върната стойност. MSVC 2015 RC има същото ограничение.

constexpr even(int n) { return (n & 1) == 0; } // valid c++11/14
constexpr even(int n) { return (n & 1) ? true : false; } // valid c++11/14
constexpr even(int n) { // valid c++14, not valid c++11
    if ((n & 1) == 0)
        return true;
    return false;
}
person kfsone    schedule 28.06.2015