用于检查变量是否等于可变参数之一的可变参数宏
Variadic macro for checking if variable equals one of variadic arguments
我目前正在 c++ 中开发类似 WebGL 的 OpenGL 包装器,其中涉及验证参数是否确实有效。问题或多或少是 OpenGL 有一吨,我在这里并没有夸大某些函数的有效参数。
(一个天真的条件图像(glTexImage2D
的可能 internalformat
常量,如果你有兴趣的话。我真的写了一个 JS table parser/conditional maker for a其中一些) 可以说明我的观点。那是 assert
...)
这种检查的逻辑很简单:
bool check(const unsigned int var)
{
return var == CONSTANT_1 || var == CONSTANT_2 || var == CONSTANT_...;
}
但是,根据上面的示例,这最多可以扩展 84 个可能的常量,这是......是的。而且我完全知道宏不会将其减少到荒谬的数量,但它仍然会有所作为,而且我觉得它也会更干净。更不用说其他具有不同运算符的类似方式的宏的可能性了。
所以我的想法是使用宏。毕竟,使用 std::initializer_list``,
std::vector,
std::array` 或其他一些容器,在运行时执行此检查很简单,但由于所有这些常量在编译时都是已知的,我觉得好像没必要。
由于可能的常量数量是可变的,我认为没有办法不使用可变参数宏。但是我不知道我将如何实现这一目标。我想到的一种可能的方法是根据参数的数量 (akin to this) 重载一个宏,但这似乎不必要地复杂。
本质上,我正在寻找一个可以满足以下条件的宏:
MACRO(var, CONSTANT_1, CONSTANT_2, CONSTANT_3)
扩展到
var == CONSTANT_1 || var == CONSTANT_2 || var == CONSTANT_3
任意数量的常量(重要!和困难的部分)。
你可能想使用 C++17 fold expression:
template<class... Args>
bool check(const unsigned int var, const Args&... args)
{
return ((var == args) || ...);
}
然后你可以这样调用:
check(var, CONSTANT_1, CONSTANT_2, CONSTANT_3);
这里不需要使用宏,一个简单的函数和有效值数组就可以完成工作:
#include <array>
#include <algorithm>
#include <iostream>
constexpr int CONSTANT_1 = 0;
constexpr int CONSTANT_2 = 1;
constexpr int CONSTANT_3 = 2;
constexpr int CONSTANT_4 = 3;
constexpr std::array<int, 3 > VALID_CONSTANTS = { CONSTANT_1, CONSTANT_2, CONSTANT_3 };
template <size_t N>
constexpr bool check(int value, const std::array<int, N>& values)
{
return std::find(values.begin(), values.end(), value) != values.end();
}
int main()
{
std::cout << check(CONSTANT_1, VALID_CONSTANTS) << "\n";
std::cout << check(CONSTANT_4, VALID_CONSTANTS) << "\n";
}
稍作修改,代码将在编译时完成评估:
#include <array>
#include <algorithm>
#include <iostream>
constexpr int CONSTANT_1 = 0;
constexpr int CONSTANT_2 = 1;
constexpr int CONSTANT_3 = 2;
constexpr int CONSTANT_4 = 3;
struct VALID_CONSTANTS
{
static constexpr std::array<int, 3 > values = { CONSTANT_1, CONSTANT_2, CONSTANT_3 };
};
template <typename Values>
constexpr bool check(int value)
{
return std::find(Values::values.begin(), Values::values.end(), value) != Values::values.end();
}
int main()
{
std::cout << check<VALID_CONSTANTS>(CONSTANT_1) << "\n";
std::cout << check<VALID_CONSTANTS>(CONSTANT_4) << "\n";
}
您不需要宏。如果您在 constexpr std::array
中有常量,则可以按如下方式使用 std::any_of
:
#include <algorithm> // std::any_of
inline static constexpr std::array<unsigned int, 2> arr_of_const{ CONSTANT_1, CONSTANT_2 };
consteval bool check(unsigned int var)
{
return std::any_of(arr_of_const.cbegin(), arr_of_const.cend(), [var](auto ele) { return var == ele; });
}
我目前正在 c++ 中开发类似 WebGL 的 OpenGL 包装器,其中涉及验证参数是否确实有效。问题或多或少是 OpenGL 有一吨,我在这里并没有夸大某些函数的有效参数。
glTexImage2D
的可能 internalformat
常量,如果你有兴趣的话。我真的写了一个 JS table parser/conditional maker for a其中一些) 可以说明我的观点。那是 assert
...)
这种检查的逻辑很简单:
bool check(const unsigned int var)
{
return var == CONSTANT_1 || var == CONSTANT_2 || var == CONSTANT_...;
}
但是,根据上面的示例,这最多可以扩展 84 个可能的常量,这是......是的。而且我完全知道宏不会将其减少到荒谬的数量,但它仍然会有所作为,而且我觉得它也会更干净。更不用说其他具有不同运算符的类似方式的宏的可能性了。
所以我的想法是使用宏。毕竟,使用 std::initializer_list``,
std::vector,
std::array` 或其他一些容器,在运行时执行此检查很简单,但由于所有这些常量在编译时都是已知的,我觉得好像没必要。
由于可能的常量数量是可变的,我认为没有办法不使用可变参数宏。但是我不知道我将如何实现这一目标。我想到的一种可能的方法是根据参数的数量 (akin to this) 重载一个宏,但这似乎不必要地复杂。
本质上,我正在寻找一个可以满足以下条件的宏:
MACRO(var, CONSTANT_1, CONSTANT_2, CONSTANT_3)
扩展到
var == CONSTANT_1 || var == CONSTANT_2 || var == CONSTANT_3
任意数量的常量(重要!和困难的部分)。
你可能想使用 C++17 fold expression:
template<class... Args>
bool check(const unsigned int var, const Args&... args)
{
return ((var == args) || ...);
}
然后你可以这样调用:
check(var, CONSTANT_1, CONSTANT_2, CONSTANT_3);
这里不需要使用宏,一个简单的函数和有效值数组就可以完成工作:
#include <array>
#include <algorithm>
#include <iostream>
constexpr int CONSTANT_1 = 0;
constexpr int CONSTANT_2 = 1;
constexpr int CONSTANT_3 = 2;
constexpr int CONSTANT_4 = 3;
constexpr std::array<int, 3 > VALID_CONSTANTS = { CONSTANT_1, CONSTANT_2, CONSTANT_3 };
template <size_t N>
constexpr bool check(int value, const std::array<int, N>& values)
{
return std::find(values.begin(), values.end(), value) != values.end();
}
int main()
{
std::cout << check(CONSTANT_1, VALID_CONSTANTS) << "\n";
std::cout << check(CONSTANT_4, VALID_CONSTANTS) << "\n";
}
稍作修改,代码将在编译时完成评估:
#include <array>
#include <algorithm>
#include <iostream>
constexpr int CONSTANT_1 = 0;
constexpr int CONSTANT_2 = 1;
constexpr int CONSTANT_3 = 2;
constexpr int CONSTANT_4 = 3;
struct VALID_CONSTANTS
{
static constexpr std::array<int, 3 > values = { CONSTANT_1, CONSTANT_2, CONSTANT_3 };
};
template <typename Values>
constexpr bool check(int value)
{
return std::find(Values::values.begin(), Values::values.end(), value) != Values::values.end();
}
int main()
{
std::cout << check<VALID_CONSTANTS>(CONSTANT_1) << "\n";
std::cout << check<VALID_CONSTANTS>(CONSTANT_4) << "\n";
}
您不需要宏。如果您在 constexpr std::array
中有常量,则可以按如下方式使用 std::any_of
:
#include <algorithm> // std::any_of
inline static constexpr std::array<unsigned int, 2> arr_of_const{ CONSTANT_1, CONSTANT_2 };
consteval bool check(unsigned int var)
{
return std::any_of(arr_of_const.cbegin(), arr_of_const.cend(), [var](auto ele) { return var == ele; });
}