c++:使用 constexpr 对数据进行 XOR 不起作用
c++: using constexpr to XOR data doesn't work
这是我的代码:
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;
}
这是我正在阅读的论文中的代码 Here。思路很简单,对XOR
的参数OBFUSCATED1
进行解密,然后解密回原来的值。
我遇到的问题是 VS 2017
给我错误提示 function call must have a constant value in constant expression
。
如果我只离开 OBFUSCATED1("Post Malone");
,我没有错误,程序是 运行,但我注意到如果我在 constexpr MetaString1
构造函数中有断点,断点就会命中,这意味着 constexpr
不会在编译时求值。据我了解,这是因为我没有 "force"
编译器在编译期间通过将结果分配给 constexpr
变量来评估它。
所以我有两个问题:
为什么我有错误 function call must have a constant value in constant expression
?
为什么人们在使用constexpr
函数时使用template
classes?据我所知,template
classes 在编译期间得到评估,因此使用 template
class 和 constexpr
只是一种推动编译器在编译期间评估这些功能的方法?
- 您尝试将非 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;
}
这是我的代码:
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;
}
这是我正在阅读的论文中的代码 Here。思路很简单,对XOR
的参数OBFUSCATED1
进行解密,然后解密回原来的值。
我遇到的问题是 VS 2017
给我错误提示 function call must have a constant value in constant expression
。
如果我只离开 OBFUSCATED1("Post Malone");
,我没有错误,程序是 运行,但我注意到如果我在 constexpr MetaString1
构造函数中有断点,断点就会命中,这意味着 constexpr
不会在编译时求值。据我了解,这是因为我没有 "force"
编译器在编译期间通过将结果分配给 constexpr
变量来评估它。
所以我有两个问题:
为什么我有错误
function call must have a constant value in constant expression
?为什么人们在使用
constexpr
函数时使用template
classes?据我所知,template
classes 在编译期间得到评估,因此使用template
class 和constexpr
只是一种推动编译器在编译期间评估这些功能的方法?
- 您尝试将非 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;
}