自C++98起就有效的构造,在C++20与 C++23之间的行为是否存在差异?
也只是为了好玩,我在尝试编写一个程序,完全基于各标准之间的语法怪癖来检测C++的版本。我已经凑齐了除最新标准之外的所有解决方案。
#include <iostream>
#include <string>
#define u8 "\x01"
#define M(x, ...) __VA_ARGS__
struct B {};
struct A
{
bool operator==(B const&);
};
bool A::operator ==(B const&) {
return false;
}
bool operator==(B const&, A const&) {
return true;
}
int main() {
int m[] = { M(1'2, 3'4, 5) };
B b;
A a;
// C++98's preprocessor substitutes the u8 we #define'd;
// later standards see it as starting a Unicode string.
// https://stackoverflow.com/a/6402166/29080386
if (u8"\0"[0]) {
std::cout << "C++98" << std::endl;
// C++14 introduced the ' character as a digit separator;
// earlier standards interpret it as a character literal
// regardless of context.
// https://stackoverflow.com/a/23980931/29080386
} else if (m[0] == 5) {
std::cout << "C++11" << std::endl;
// C++14 was the last to support trigraphs.
// It will interpret ??= as "#"; later standards see '?'.
} else if ("??="[0] == '#') {
std::cout << "C++14" << std::endl;
// C++17 calls the global function; C++20 calls the member function.
// https://stackoverflow.com/q/64130311/29080386
} else if (b == a) {
std::cout << "C++17" << std::endl;
} else {
std::cout << "C++20" << std::endl;
}
return 0;
}
我还没能在C++23中发现这样的、既有效又会破坏向后兼容性的改动。有吗?
解决方案
P2128R6,多维下标运算符(operator[] 带有多个参数):
struct Index {
char operator[](int);
template<typename T>
static char(& test(int))[sizeof((*static_cast<T*>(0))[0, 0])];
template<typename T>
static char(& test(long))[2];
enum { is_cxx23 = sizeof(test<Index>(0)) == 2 };
};
你可以用它来区分C++20与 C++23(is_cxx23 仅在C++23及更高版本为真,在C++98与 C++20之间为假): https://godbolt.org/z/hPnacEqa7
} else if (b == a) {
std::cout << "C++17" << std::endl;
} else if (!Index::is_cxx23) {
std::cout << "C++20" << std::endl;
} else {
std::cout << "C++23" << std::endl;
}
以前,t[0, 0] 是一个逗号表达式,与 t[(0, 0)] 相同,其中左侧的 0 会被丢弃,变成 t[0]。自C++23以来,它尝试调用一个接受两个参数的 operator[] 的重载,虽然这个重载并不存在,但可以通过SFINAE来进行检查。
附注:你可以在编译时完成所有这些检查(纯粹基于语法,而不是在运行时检查任何内容): https://godbolt.org/z/nf77zfKv1
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。