5

所以如果我做这样的事情:

#include <ios>

using std::forward;

template<class T>
struct pod_version final{
    private:
        alignas(T) uint8_t m_data[sizeof(T)];
    public:
        pod_version()=default;
        pod_version(const pod_version&)=default;
        pod_version(pod_version&&)=default;
        ~pod_version()=default;
        pod_version& operator=(const pod_version&)=default;
        pod_version& operator=(pod_version&&)=default;

        template<class...V>void construct(V&&...v){
            new (m_data) T(forward<V>(v)...);
        }

        void destroy(){
            reinterpret_cast<T*>(m_data)->~T(); // g++: warning typed punned blah im allowed to break ur code LOL
            reinterpret_cast<T*>(this)->~T(); // g++: :D
        }
};

int main(){
    pod_version<int> x;
    x.construct(5);
    x.destroy();
    return 0;
}

注意:“m_data”和“this”应该指向同一个地方...

GCC 4.8.1

4

3 回答 3

1

使用char,不使用uint8_t

类型双关语规则对、 和有特殊情况char,并且只有这些类型。 不需要表示其中之一。signed charunsigned charuint8_t

请注意,这个pod_version类的整个概念是可疑的。您正在对无效的类型强制执行简单的复制语义。您的代码将尝试在未初始化的内存或对象的二进制图像上调用析构函数。两者都会导致未定义的行为。

于 2014-01-11T20:52:15.910 回答
0

标准不要求警告。实现可能会以任何他们认为合适的原因警告您,或者根本不会警告您。

值得一提的是,gcc 4.8.2 使用-Wall. 编辑:不,它没有。

于 2014-01-11T21:45:13.963 回答
0

您的编译器正确地抱怨了m_data因为m_data不是类型char*而是类型的转换int8_t*。严格的别名规则不允许与除 a或char*之外的任何内容进行类型双关语。unsigned char*signed char*

很可能,编译器无法通过将 a 转换pod_version<T>*为 a来判断出一些邪恶的东西T*。毕竟,这些都是复杂类型,编译器不知道T您将访问哪些成员,它可能是一个int8_t成员,在这种情况下,强制转换是完全可以的。毕竟,未定义的行为仅在您以不同的基本类型访问相同的内存位置时调用,而不是在您更改指针的类型时调用。

在任何情况下,您都可以通过编写演员表明确地告诉编译器“我知道我在做什么”,因此任何健全性检查都是可选的。

于 2014-01-11T20:52:33.243 回答