c++ - 如何通过内联函数强制 const 传播?

标签 c++ c-preprocessor constexpr

我试图强制预处理器为我执行一些数学运算,以便将常量传播到内联汇编中。这是简化的情况:

inline
unsigned int RotateRight(unsigned char value, unsigned int amount)
{
    COMPILE_ASSERT(((unsigned char)(amount%32)) < 32);
    __asm__ ("rorb %1, %0" : "+mq" (value) : "I" ((unsigned char)(amount%32)));
    return value;
}

上面的代码依赖于特定于 CPU 的功能,我对此很满意(它实际上是在 GCC 可用时 x86/x64 Linux 上的模板特化)。 "I" 约束表示整数值必须介于 [0,31] 之间(含)。

代码的调用者看起来像:

byte b1 = RotateRight(1, 1);
byte b2 = RotateRight(1, 31);

RotateRight(1, 31) 来自密码学家(它在 C/C++ 中的未定义行为,因为一个字节只能在 [0,7] 范围内旋转).我可以使用 ASM 摆脱 C/C++ 的约束。而且由于移位量在编译时已知,我希望在编译时减少它;我想要使​​用生成的立即数 8 的 rorb 版本。

没有 COMPILE_ASSERT,代码可以编译,但我不确定常量是否正在传播。也就是说,它可能会以意外的减少生成 (%32)。使用 COMPILE_ASSERT,代码无法编译。

$ make validat1.o
g++ -DNDEBUG -g2 -O3 -march=native -pipe -c validat1.cpp
In file included from simple.h:10:0,
                 from filters.h:6,
                 from files.h:5,
                 from validat1.cpp:6:
misc.h: In function ‘T CryptoPP::rotlFixed(T, unsigned int) [with T = unsigned char]’:
misc.h:940:43: error: ‘y’ cannot appear in a constant-expression
  CRYPTOPP_COMPILE_ASSERT(((unsigned char)(y%32)) < 32);
                                           ^
misc.h:72:85: note: in definition of macro ‘CRYPTOPP_COMPILE_ASSERT_INSTANCE’
 _COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)>

我知道我不应该使用 #define,而 C++ 内联函数就是答案。但我觉得我正在遭受脱节。

如何强制编译器传播涉及 const 值的值?

或者,如果 COMPILE_ASSERT 是错误的工具(正在传播 const),我该如何设置测试以便验证 immediate-8 版本是否使用了 rorb


相关,这是一个C++03项目。它不使用Boost,不使用Cmake,不使用Autotools等。

最佳答案

当您指定 amount 作为函数参数时,您将失去其编译时常量性。

你为什么不声明 amount 是模板参数?在这种情况下,函数用户也被迫传递一个编译时常量,这也很好。

要确保将 shift 用作编译时常量,您可以创建一个 static const 局部变量。

template<unsigned int amount> inline
unsigned int RotateRight(unsigned char value)
{
    static const unsigned char shift = (unsigned char)(amount%32);
    __asm__ ("rorb %1, %0" : "+mq" (value) : "I" (shift));
    return value;
}

关于c++ - 如何通过内联函数强制 const 传播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31498412/

相关文章:

C++ 互斥锁定错误

c++ - 哪些 Netbeans 8.2 项目文件应该提交给 C++ 项目的版本控制?

c++ - 为什么 constexpr 可以解决重复定义问题?

c++ - 未捕获 constexpr 变量

c++ - _endthreadex(0) 挂起

c++ - 使用 jsoncpp 时从 JSON 中剥离私有(private)数据的最佳方法

c++ - QT_NO_DEBUG 是否会导致 NDEBUG 的定义?

c++ - 预处理器中的命令连接

c - 宏 if 语句返回错误 : operator '&&' has no right operand

c++ - 为什么要为字符串文字声明将const添加到constexpr中?