MSVC无法编译以下代码(https://godbolt.org/z/feenYcaen):
错误C2131:表达式的计算结果不是常数
第10行来自MSVC自己的offsetof
,我觉得这个语句是常量表达式,即使不是,MSVC运行时不能计算这个吗,这是MSVC的bug吗?
#include <type_traits>
#include <iostream>
struct A{};
template<typename T, A T::*MPtr>
struct KKP {
private:
static const std::uintptr_t c =
((size_t) & reinterpret_cast<char const volatile&>((((T*)0)->*MPtr)));
};
struct PC {
A t;
};
size_t f() {
KKP<PC, &PC::t> ar;
}
事实上,我通过使用成员函数而不是类成员(https://godbolt.org/z/c65eEnvd7)解决了这个问题,但MSVC对我来说变得更加混乱:
#include <type_traits>
#include <iostream>
struct A{};
template<typename T, A T::*MPtr>
struct KKP {
private:
static constexpr size_t c() {
return ((::size_t) & reinterpret_cast<char const volatile&>((((T*)0)->*MPtr)));
}
};
struct PC {
A t;
};
size_t f() {
KKP<PC, &PC::t> ar;
return 0;
}
1条答案
按热度按时间cuxqih211#
offsetof无法在标准C中实现,需要编译器支持-cppreference
从引文中可以看出,这两个代码示例都不符合C标准。
在应该为
constexpr
的表达式中存在空指针解引用未定义行为和reinterpret_cast
转换。Both do not belong to core constant expressions:核心常量表达式是其计算不会计算以下任何一项的任何表达式:
8.其求值导致任何形式的核心语言未定义行为的表达式...
18.重新解释转换
在第二个代码示例中,问题仍然存在,因为函数实际上不是
constexpr
,并且程序的格式不正确。constexpr函数必须满足以下要求:
对于constexpr函数模板和类模板的constexpr成员函数,至少有一个专门化必须满足上述要求。其他专门化仍然被认为是constexpr,即使对这样的函数的调用不能出现在常量表达式中。* 如果模板的任何专门化在被认为是非模板函数时都不能满足constexpr函数的要求,则该模板是病态的。不需要诊断(C++23之前)*. cppreference
考虑example