gpt4 book ai didi

c++ - 在静态断言和运行时错误之间自动选择

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:50:16 26 4
gpt4 key购买 nike

我有执行除法和检查对齐的宏。

#define BYTES_TO_WORDS(x)  ((CHECK_ALIGNMENT(x,2)) * ((x) / 2))

我想将 CHECK_ALIGNMENT 实现为一个始终返回 1 的宏,如果 x 不除以 2 则触发错误。
BYTES_TO_WORDS 从不同的上下文调用,有时使用 x 作为编译时常量整数表达式,有时使用 x 作为整数表达式在运行时解决。

是否可以实现 CHECK_ALIGNMENT,以便在使用常量表达式调用宏时执行 static_assert,并在表达式不是编译时执行一些运行时错误检查-时间常数?
我可以更改宏定义,但不能更改调用和使用宏的方式。

这是一个可能的解决方案(并不总是有效):

#define CHECK_ALIGNMENT(x,alignedTo) (1/(((alignedTo)-((x)%(alignedTo)))/(alignedTo)))

在此实现中,我们应该在运行时或编译时遇到被零除错误,具体取决于输入。
然而,由于 compiler bug,这并不总是有效.此外,错误消息不是很好。

更好的解决方案是识别参数是否为编译时常量,并在这种情况下使用 static_assert,并附上漂亮的编译时错误消息。如果参数不代表编译时常量,则在运行时检查对齐。

这可能吗?
我需要它才能在 Visual Studio 2015 上工作。


澄清

评论中有一些关于为什么我在 C++ 问题中使用宏的讨论。
BYTES_TO_WORDS 宏位于头文件中,各种工具都包含该头文件,C++ 编译器就是其中之一。
其他工具使用此宏并评估算术表达式 ((x)/2),但在这些工具上,我将 CHECK_ALIGNMENT 定义为 1,因为它们无法处理 constexpr、模板甚至函数调用。
使用 C++ 编译器编译此 header 时,我想将 CHECK_ALIGNMENT 定义为其他内容,这将在需要时触发 static_assert 或运行时错误。
CHECK_ALIGNMENT 的定义可以是任何 C++11 代码(或 VS2015 支持的 C++14),可以使用模板、constexpr 或诸如此类的东西。

最佳答案

我能想到的唯一解决方案要求您在将编译时常量用于您提供的宏之前包装它们。

所以下面的代码“自动”在编译时错误或运行时错误之间进行选择,只要您记得通过包装它们来正确指示编译时常量。请注意,由于转换运算符,包装器还会自动转换为普通的 int

另外,一定要看看 Boost.Hana在使用我为概念实现证明创建的 Constant 类之前。下面介绍的实现不是通用的(它只包装 int 并且只转换回 int)并且严重缺乏功能。


#include <iostream>
#include <stdexcept>

template <int I>
struct Constant
{
constexpr Constant() = default;

constexpr operator int () const
{
return I;
}
};

template <int I = 0>
constexpr int check_alignment(Constant<I>)
{
static_assert(I % 2 == 0, "Error: not divisible by 2!");
return 1;
}

int check_alignment(int value)
{
if (value % 2 != 0)
throw std::runtime_error("Error: not divisible by 2!");

return 1;
}

#define CHECK_ALIGNMENT(x) check_alignment(x)
#define BYTES_TO_WORDS(x) ((CHECK_ALIGNMENT(x)) * ((x) / 2))

int main()
{
constexpr Constant<2> c2;
constexpr Constant<3> c3;
constexpr Constant<4> c4;

// Compile-time checks:
static_assert(BYTES_TO_WORDS(c2) == 1, "Error!");
static_assert(BYTES_TO_WORDS(c2) == 2, "Error!"); // "Error!"
static_assert(BYTES_TO_WORDS(c3) == 2, "Error!"); // "Error: not divisible by 2!"
static_assert(BYTES_TO_WORDS(c4) == 2, "Error!");
static_assert(BYTES_TO_WORDS(c4) == 4, "Error!"); // "Error!"

// Runtime checks:
std::cout << BYTES_TO_WORDS(2) << std::endl; // outputs "1"
std::cout << BYTES_TO_WORDS(3) << std::endl; // "Runtime error: Error: not divisible by 2!"
std::cout << BYTES_TO_WORDS(4) << std::endl; // outputs "2"

return 0;
}

关于c++ - 在静态断言和运行时错误之间自动选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42649007/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com