C++程序(有点出乎意料,起初对我来说)编译并运行正常,除了在结尾处注释的行main()
,如果它被取消注释则是编译时错误.
#include <typeinfo>
#include <iostream>
struct Foo {
int x;
};
template <typename T>
void create(char *buffer)
{
std::cout << "creating " << typeid(T).name() << std::endl;
new (buffer) T();
}
template <typename T>
void destroy(char *buffer)
{
std::cout << "destroying " << typeid(T).name() << std::endl;
((T*)buffer)->~T();
}
int main(int argc, char **argv)
{
char buffer[sizeof(Foo) > sizeof(bool) ? sizeof(Foo) : sizeof(bool)];
// create/destroy Foo via template function calls
create<Foo>(buffer);
destroy<Foo>(buffer);
// now do the above explicitly...
new (buffer) …
Run Code Online (Sandbox Code Playgroud) 我知道浮点运算和精度损失的常见问题,所以这不是关于为什么0.1 + 0.2 != 0.3
等的常见问题.
相反,我实际上想用C++(以100%标准兼容的方式)实现二进制谓词,它实际上实现了真正的数学等价关系(即反身,传递和对称),这样两个双精度在同一个等价中class,如果它们在所有方面都代表完全相同的值,区分像是0.0
和-0.0
但是将所有NaN
值视为在同一等价类中的极端情况.(特别是,默认==
值不是我想要的,因为在情况下是非反身的NaN
,并且不区分0.0
和否定-0.0
,我希望在不同的等价类中,因为它们实际上是不同的值并且导致不同的运行时行为).
什么是最简单和最简单的方法,不依赖于任何方式的类型惩罚或任何实现定义的行为?到目前为止我有:
#include <cmath>
bool equiv(double x, double y)
{
return (x == y && (x != 0.0 || std::signbit(x) == std::signbit(y))) ||
(std::isnan(x) && std::isnan(y));
}
Run Code Online (Sandbox Code Playgroud)
我相信这可以处理我所知道并在前面描述过的角落情况,但是还有其他一些不能处理的角落情况吗?上面的二元谓词是否保证根据C++标准定义等价关系,或者是未指定的任何行为,实现定义的等等?
我处于这样一种情况,我在两个类的定义之间有一个循环依赖循环,其中(据我所知)两个类都需要另一个类型才能成为完整类型才能正确定义它们.
简而言之,我需要简化版本的内容:
struct Map;
struct Node {
// some interface...
private:
// this cannot be done because Map is an incomplete type
char buffer[sizeof(Map)];
// plus other stuff...
void* dummy;
};
struct Map {
// some interface...
private:
// this is Map's only member
std::unordered_map<std::string, Node> map_;
};
Run Code Online (Sandbox Code Playgroud)
这种情况实际上比上面更复杂,因为Node
它实际上将是一个变体类型(类似于boost::variant
),它使用placement new来显式构造预分配中的多种类型的对象之一(并且具有正确的对齐,我忽略了在这个简化中)缓冲区:因此缓冲区不是精确的sizeof(Map)
,而是依赖于某个计算的常量sizeof(Map)
.
显然,问题是只在前向声明时才sizeof(Map)
可用Map
.此外,如果我Node
首先将声明的顺序更改为forward declare ,那么编译Map
失败,因为std::unordered_map<std::string, Node>
在Node
不完整类型时无法实例化,至少在Ubuntu上使用我的GCC 4.8.2.(我知道这取决于libstdc ++版本比GCC版本更多,但我不知道如何找到它......)
作为替代方案,我正在考虑以下解决方法:
struct Node { …
Run Code Online (Sandbox Code Playgroud)