c ++: использование constexpr для данных XOR не работает - PullRequest
0 голосов
/ 02 мая 2019

Вот мой код:

template<int... I>
class MetaString1
{
public:
    constexpr MetaString1(constexpr char* str)
        : buffer_{ encrypt(str[I])... } { }

const char* decrypt()
{
    for (int i = 0; i < sizeof...(I); ++i)
        buffer_[i] = decrypt1(buffer_[i]);
    buffer_[sizeof...(I)] = 0;
    return buffer_;
}

private:
    constexpr char encrypt(constexpr char c) const { return c ^ 0x55; }
    constexpr char decrypt1(constexpr char c) const { return encrypt(c); }

private:
    char buffer_[sizeof...(I)+1];

};


#define OBFUSCATED1(str) (MetaString1<0, 1, 2, 3, 4, 5>(str).decrypt())



int main()
{

    constexpr char *var = OBFUSCATED1("Post Malone");

    std::cout << var << std::endl;
    return 1;
}

Это код из статьи, которую я читаю Здесь .Идея проста, XOR аргумент OBFUSCATED1, а затем расшифровать обратно к исходному значению.

Проблема, с которой я столкнулся, заключается в том, что VS 2017 дает мне ошибку, говоря: function call must have a constant value in constant expression.

Если я оставлю только OBFUSCATED1("Post Malone");, у меня не будет ошибок и программа будет запущена, ноЯ заметил, что если у меня есть точки останова в конструкторе constexpr MetaString1, точка останова попадает, что означает, что constexpr не оценивается во время компиляции.Как я понимаю, это потому, что я не "force" компилятор, чтобы оценить его во время компиляции, присваивая результат переменной constexpr.

Поэтому у меня есть два вопроса:

  1. Почему у меня ошибка function call must have a constant value in constant expression?

  2. Почему люди используют template классы, когда они используют constexpr функции?Как я знаю, template классы оцениваются во время компиляции, поэтому использование template класса с constexpr - это просто способ заставить компилятор оценить эти функции во время компиляции?

1 Ответ

0 голосов
/ 03 мая 2019
  1. Вы пытаетесь присвоить тип не constexpr переменной типа constexpr, что невозможно
constexpr char *var = OBFUSCATED1("Post Malone")
//              ^^^   ^^^^^^^^^^^
// type of var is constexpr, return type of OBFUSCATED1 is const char*

Ключевое слово constexpr было введено в C ++ 11, поэтому, прежде чем иметь это ключевое слово, вам нужно было написать сложный материал TMP, чтобы компилятор делал вещи во время компиляции.Поскольку TMP завершается, вы теоретически не нуждаетесь в чем-то большем, чем TMP, но, поскольку TMP медленно компилируется и уродлив до готовности, вы можете использовать constexpr, чтобы выразить то, что вы хотите оценить во время компиляции, в более удобочитаемом виде.,Хотя между TMP и constexpr нет корреляции, это означает, что вы можете использовать constexpr без шаблонных классов.

Чтобы достичь желаемого, вы можете сохранить обе версии строки:

template <class T>
constexpr T encrypt(T l, T r)
{
    return l ^ r;
}
template <std::size_t S, class U>
struct in;
template <std::size_t S, std::size_t... I>
struct in<S, std::index_sequence<I...>>
{
    constexpr in(const char str[S])
        : str_{str[I]...}
        , enc_{encrypt(str[I], char{0x12})...}
    {}
    constexpr const char* dec() const
    {
        return str_;
    }
    constexpr const char* enc() const
    {
        return enc_;
    }

protected:
    char str_[S];
    char enc_[S];
};
template <std::size_t S>
class MetaString1
    : public in<S, std::make_index_sequence<S - 1>>
{
public:
    using base1_t = in<S, std::make_index_sequence<S - 1>>;
    using base1_t::base1_t;
    constexpr MetaString1(const char str[S])
        : base1_t{str}
    {}
};

И используйте это так:

int main()
{
    constexpr char str[] = "asdffasegeasf";
    constexpr MetaString1<sizeof(str)> enc{str};
    std::cout << enc.dec() << std::endl;
    std::cout << enc.enc() << std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...