Eric Niebler 前段时间写了一篇关于Universal References
以下内容的文章Copy Constructor
:
最后的解决方案是
template <typename A, typename B>
using disable_if_same_or_derived = std::enable_if_t<!std::is_base_of_v<A, std::remove_reference_t<B>>>;
缺点是std::is_base_of_v需要类型参数的完整定义。无法将其与转发类型一起使用。
我现在可以使用 c++20,想知道我们是否可以找到解决方案。你有什么想法吗?
添加标记类型,如
std::piecewise_construct_t
或类似,将完美转发构造函数标记为非复制/移动构造函数。然后,当使用这种类型时,您可以在构造函数调用前加上
std::piecewise_construct_t
或类似的前缀。这些标记类型的理念是,它们是构造函数要遵循的“指令”。当它们完成时,“is base of”的第一个参数的测试也将完成。
实际上,很少有类会将其构造函数参数转发到其他不透明的地方,而这些参数没有特殊含义。即使是元组;即使元组只有一个元素,我们也会构造元组的内容。
一旦我们有了“包装”的含义,我们就可以将其表达为标记指令。该标记指令可以是显式的,它不会变魔术并检测其其他参数的属性。这允许传递不完整类型而无需了解它们的工作原理。
一般来说,检测“这种类型是否不完整”并表现出不同的行为永远是不安全的,因为 C++ 标准是这样措辞的,任何在同一个编译单元中对完整和不完整类型表现不同的模板都会导致程序格式错误,不需要进行诊断;即使在编译单元之间,由于一个定义规则,事情通常也不起作用。