中定义的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"TU 1中的std::piecewise_construct指的是与TU 2中的f不同的对象,我怀疑f违反了ODR。
N3290 (可能也是ISO/IEC 14882:2011 )指出,在3.2/5中,以下情况是ODR的一个例外:
如果对象在D的所有定义中具有相同的文字类型,并且使用常量表达式(5.19)初始化对象,并且使用对象的值(而不是地址),则名称可以引用具有内部链接或无链接的const对象,并且该对象在D的所有定义中具有相同的值;
f几乎满足了所有的需求,但是在我看来,“使用对象的值(而不是地址)”似乎不明确。的确,std::piecewise_construct_t没有状态,但是对std::pair的分段构造函数的调用涉及对std::piecewise_construct_t的隐式声明的复制构造函数的调用,该构造函数的参数是const std::piecewise_construct_t &。地址是“用”的,不是吗?
我很困惑。
参考资料:http://lists.boost.org/Archives/boost/2007/06/123353.php
发布于 2011-10-03 11:55:32
似乎你已经有了你的答案,在那个boost邮件列表张贴。是的,在我看来,这是未定义的行为,或者至少没有足够明确的定义行为。
有关正在讨论的同一事项,请参见这个usenet的讨论。
发布于 2011-10-03 12:03:42
国际水文学组织在民主解决方案下没有冲突。
未命名的命名空间与为内部链接(静态)标记事物具有相同的效果。这实际上意味着每个TU都对这类类型/函数使用了自己独特的定义。
我看待它们的方式,即占位符(::::_1和相竞争的味道)是如何工作的,与其说是通过实例化,不如说是通过编译时类型推断:
_1、_2等只是占位符,它们实际上不需要兼容(值不需要从一个TU传递到另一个TU,它们仅作为类型推断参数传递,因此它们的实际类型被推断为具有当前TU的identity )。
IOW:你可以很容易地定义你自己的占位符,通过专门化一些特征,它们仍然应该像魅力一样发挥作用。
namespace boost
{
template<int I> struct is_placeholder<
my_funny_own_placeholder_no_ODR_involved<I> >
{
enum _vt { value = I };
};
}我认为同样的逻辑也适用于piecewise_construction (但我还没有看那么多)。
https://stackoverflow.com/questions/7634419
复制相似问题