[英]generate a string at compile time based on some condition
I wanted to generate fopen()
's open mode parameter at compile-time ( file::get_mode()
) 我想在编译时生成
fopen()
的打开模式参数( file::get_mode()
)
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
enum open_mode {
read = (1u << 0),
write = (1u << 1),
binary = (1u << 2),
update = (1u << 3)
};
template<int open_type>
class file {
public:
constexpr static int is_read_mode() {
return CHECK_BIT(open_type,0);
}
constexpr static int is_write_mode() {
return CHECK_BIT(open_type,1);
}
constexpr static int is_binary_mode() {
return CHECK_BIT(open_type,2);
}
constexpr static int is_update_mode() {
return CHECK_BIT(open_type,3);
}
constexpr static const void get_mode(char (&mode)[5]) {
int len = 0;
if constexpr(is_read_mode())
mode[len++] = 'r';
if constexpr(is_write_mode())
mode[len++] = 'w';
if constexpr(is_binary_mode())
mode[len++] = 'b';
if constexpr(is_update_mode())
mode[len++] = '+';
mode[len++] = 0;
}
};
but even though everything inside the file::get_mode()
can be determined at compile-time (as far as I can think) but i don't think it's computing at compile-time as the following code is not compiling because of the last assertion, removing the last assertion code compiles fine and runs 但是即使
file::get_mode()
内的所有内容都可以在编译时确定(据我所知),但是我不认为它在编译时正在计算,因为以下代码由于最后一个而无法编译断言,删除最后的断言代码可以正常编译并运行
int main() {
file<open_mode::write> f;
char mode[5];
f.get_mode(mode);
static_assert(mode[0] == 'w');
}
so my question is: how can I generate this at compile-time? 所以我的问题是:如何在编译时生成此代码?
You're using if constexpr
so you're using C++17. 您正在使用
if constexpr
因此您正在使用C ++ 17。
In C++17 the operator[]
is constexp
so, instead of passing and modifying a C-style array, you can generate an return a std::array
. 在C ++ 17中,
operator[]
是constexp
因此可以传递std::array
而不是传递和修改C样式的std::array
。
I mean 我的意思是
constexpr static auto get_mode ()
{
std::array<char, 5U> ret {}; // initialize to `\0` all chars
std::size_t pos = -1;
if constexpr ( is_read_mode() ) ret[++pos] = 'r';
if constexpr ( is_write_mode() ) ret[++pos] = 'w';
if constexpr ( is_binary_mode() ) ret[++pos] = 'b';
if constexpr ( is_update_mode() ) ret[++pos] = '+';
return ret;
}
so you can write something as 所以你可以写一些东西
static_assert( f.get_mode()[0] == 'w' );
static_assert( f.get_mode()[1] == '\0' );
En passant: remember to make is_*_mode()
functions returning bool
, not int
. 注意:请记住使
is_*_mode()
函数返回bool
,而不是int
。
The following is a full compiling example 以下是完整的编译示例
#include <array>
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
enum open_mode {
read = (1u << 0),
write = (1u << 1),
binary = (1u << 2),
update = (1u << 3)
};
template <int open_type>
struct file
{
constexpr static bool is_read_mode() { return CHECK_BIT(open_type,0); }
constexpr static bool is_write_mode() { return CHECK_BIT(open_type,1); }
constexpr static bool is_binary_mode() { return CHECK_BIT(open_type,2); }
constexpr static bool is_update_mode() { return CHECK_BIT(open_type,3); }
constexpr static auto get_mode ()
{
std::array<char, 5U> ret {};
std::size_t pos = -1;
if constexpr ( is_read_mode() ) ret[++pos] = 'r';
if constexpr ( is_write_mode() ) ret[++pos] = 'w';
if constexpr ( is_binary_mode() ) ret[++pos] = 'b';
if constexpr ( is_update_mode() ) ret[++pos] = '+';
return ret;
}
};
int main ()
{
file<open_mode::write> fw;
static_assert( fw.get_mode()[0] == 'w' );
static_assert( fw.get_mode()[1] == '\0' );
file<open_mode::read | open_mode::write> frw;
static_assert( frw.get_mode()[0] == 'r' );
static_assert( frw.get_mode()[1] == 'w' );
static_assert( frw.get_mode()[2] == '\0' );
}
char mode[5]
is not constexpr
, so it might change its values in runtime. char mode[5]
不是constexpr
,因此它可能会在运行时更改其值。 Instead, you could return a string literal from get_mode()
. 相反,您可以从
get_mode()
返回字符串文字。 You should also modify the logic to prevent invalid access modes (for example, if you want both read and write, you should use w+
or r+
, not wr
). 您还应该修改逻辑以防止无效的访问模式(例如,如果要同时进行读取和写入,则应使用
w+
或r+
,而不要使用wr
)。
constexpr static const char* get_mode() {
if (is_read_mode()) {
if (is_binary_mode()) {
return "rb";
}
else {
return "r";
}
}
// ...
}
You can use it at compile time like this: 您可以在编译时使用它,如下所示:
int main() {
file<open_mode::write> f;
static_assert(f.get_mode() == "w");
static_assert(f.get_mode()[0] == 'w');
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.