实例化不可构造对象:trivially copyable定义是否存在问题?
关于不可构造类被
std::bit_cast实例化的问题分析 我们可以设计一个不可构造的类,但我却成功实例化了它的对象:
#include <bit> #include <cstring> #include <iostream> // 不可构造 // 无隐式生命周期 struct Test { int val{1}; Test() = delete; Test(Test const&) = delete; Test(Test&&) = delete; Test& operator=(Test const&) = default; Test& operator=(Test&&) = default; ~Test() = default; }; int main() { char storage[sizeof(Test)]; int i{666}; std::memcpy(storage,&i,sizeof(Test)); auto HeWhoMustNotBeNamed = std::bit_cast<Test>(storage); std::cout << HeWhoMustNotBeNamed.val; }
所有测试编译器(GCC、Clang、MSVC)均将Test识别为**平凡可拷贝(trivially copyable)**类型。
Test和storage满足std::bit_cast的前置条件,因此Clang和MSVC可无未定义行为地创建该不可构造类的对象。
仅GCC编译失败,它尝试调用已删除的移动构造函数返回结果,推测MSVC和Clang对std::bit_cast做了拷贝消除优化,而GCC未做。
我认为该行为违反类的语义,问题出在平凡可拷贝类型的定义上——它允许存在无法拥有实例的类(尽管从逻辑上讲,所有无法存在的对象都可被平凡拷贝)。
我的分析是否有误?注:另有替代方案已作为新问题提出。
补充:该问题并非纯理论,不可构造类可作为仅用于继承的基础实现类:
// 不可构造 // 无隐式生命周期 struct BaseImpl { int val{1}; BaseImpl() = delete; BaseImpl(BaseImpl const&) = delete; BaseImpl(BaseImpl&&) = delete; BaseImpl& operator=(BaseImpl const&) = default; BaseImpl& operator=(BaseImpl&&) = default; ~BaseImpl() = default; protected: BaseImpl(int i) : val{i} {}; }; struct Concrete: private BaseImpl { Concrete(int i) : BaseImpl{i}{}; int Value() const {return BaseImpl::val;}; };
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

