std::p iecewise_construct不会导致ODR违规吗?
Doesn't std::piecewise_construct cause a ODR violation?
std::piecewise_construct
,在constexpr
以来具有内部链接。我想知道在头中使用std::piecewise_construct
是否会违反ODR。例如:
a.hpp
#include <utility>
#include <tuple>
struct point
{
point(int x, int y)
: x(x), y(y)
{}
int x, y;
};
inline std::pair<point, point> f(int x1, int y1, int x2, int y2)
{
return {
std::piecewise_construct,
std::forward_as_tuple(x1, y1), std::forward_as_tuple(x2, y2)
};
}
翻译单元1
#include "a.hpp"
翻译单元2
#include "a.hpp"
图1中f
中的std::piecewise_construct
所指的对象与图2中f
所指的对象不同。我怀疑f
违反了ODR。
N3290(可能也是ISO/IEC 14882:2011)说以下情况是ODR的例外,在3.2/5中:
如果对象在D的所有定义中具有相同的文字类型,并且使用常量表达式(5.19)初始化对象,并且使用了对象的值(但不是地址),并且该对象在D的所有定义中具有相同的值,则名称可以引用具有内部链接或不具有链接的const对象;
f
几乎满足了所有的要求,但是"使用对象的值(而不是地址)"对我来说似乎模棱两可。的确,std::piecewise_construct_t
没有状态,但是对std::pair
的分段构造函数的调用涉及到对std::piecewise_construct_t
的隐式声明的复制构造函数的调用,其参数是const std::piecewise_construct_t &
。地址是used,对吧?
我很困惑。
参考:http://lists.boost.org/Archives/boost/2007/06/123353.php
看来你已经在那个boost邮件列表帖子中得到了答案。是的,在我看来,这是一种未定义的行为,或者至少是定义不够明确的行为。
请参阅此用户组讨论以了解正在讨论的相同问题。
我认为ODR下没有冲突。
未命名的命名空间与为内部链接(静态)标记事物具有相同的效果。这确实意味着每个TU对这些类型/函数使用自己独特的定义。
我看待它们的方式,占位符(::::_1和竞争版本)如何工作,不是通过实例化,而是通过编译时类型推断:
_1, _2等只是占位符,它们并不需要真正兼容(值不需要从一个TU传递到另一个TU,它们只作为类型推断参数传递,因此它们的实际类型被推断为具有当前TU的 identity
)。
ow:你可以很容易地定义你自己的占位符通过专门的一些特征,他们应该仍然像一个魅力。
namespace boost
{
template<int I> struct is_placeholder<
my_funny_own_placeholder_no_ODR_involved<I> >
{
enum _vt { value = I };
};
}
我想同样的逻辑可以适用于piecewise_construction(但我还没有看那么多)。
- 这是 basic.def.odr 部分的缺陷吗?
- 为什么显式模板实例化不会破坏 ODR?
- (ODR 使用问题)在不同文件中priority_queue名称相同的结构
- 声明中不一致的no是否违反ODR?
- 是否使用静态 constexpr 变量 odr?
- 使用 -pthread 如何不违反 ODR 规则?
- 为什么编译器不在同一翻译单元中警告 ODR 违规
- C++ standard: ODR and constexpr std::string_view
- ODR 使用的规则不适用于 Visual Studio
- ASAN 检测与动态加载库共享的类的 vtable 的 ODR 违规
- C++模板函数的默认参数的 ODR 规则
- 为什么调用成员函数不调用该对象的 ODR-USE?
- 功能过载和ODR如何共存?(C )
- 为什么结构声明在C++中违反了 ODR
- 是具有预处理前分支实现的结构违反ODR
- 如何在C 中应用ODR(一个定义规则)
- 为什么“静态”功能在不同的tu中不会破坏ODR
- 您可以在类型上使用结构化绑定违反ODR吗?
- 为什么在标题上的结构中声明的模板不违反 ODR 并且专用化会违反 ODR
- GCC 6.3.0 中的 ODR 冲突,类型在两个单独的翻译单元中定义