2011-10-03 43 views
20

'std :: piecewise_construct',在<实用程序>中定义,因为它被声明为constexpr而具有内部链接。我想知道在标题中使用'std :: piecewise_construct'是否会违反ODR。例如:不是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) 
    }; 
} 

// translation unit 1 
#include "a.hpp" 

// translation unit 2 
#include "a.hpp" 

在TU 1 f的“标准:: piecewise_construct”是指在TU 2“F”不同的对象比我怀疑“F”违反ODR。

N3290(可能ISO/IEC 14882:2011也)表示以下情况下是ODR的一个例外,在3.2/5:

的名称可以指const对象与内部或没有连锁,如果该对象在D的所有定义中都具有相同的文字类型,并且该对象使用常量表达式(5.19)进行初始化,并且使用该对象的值(但不是地址),并且该对象具有相同的值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

+2

+1(我认为)对于一个问题,仍然有我没有线索2分钟后 – sehe

+0

这不是与'std :: cout'相同的问题? –

+1

@Kerrek'std :: cout'没有多次定义。它只是在其各自的头文件中声明。 –

回答

6

看来,你已经在提升邮件列表中你的答案。是的,我认为这是未定义的行为,或者至少没有明确定义的行为。

请参阅this usenet discussion讨论同一事项。

+0

谢谢你的回答。 – iorate

+0

我也这么认为。顺便说一句,与Boost不同,标准库不需要仅用于标题。因此'piecewise_construct'应该被声明为:'extern const piecewise_construct_t piecewise_construct;'。我想知道为什么它不是。 – iorate

+0

我建议询问comp.std.C++或comp.lang.C++。moderated。 –

0

恕我直言,在ODR下没有冲突。

未命名的名称空间与标记内部链接(静态)的效果具有相同的效果。 这确实意味着每个TU都使用他自己的这种类型/功能的唯一定义。

我看他们的样子,占位符(:::: _ 1和竞争的味道)是如何工作的,不能被实例化这么多的编译时类型推断:

_1,_2等仅仅是占位符,并且它们并不需要兼容(值不需要从一个TU传递到另一个,它们仅作为类型推断的参数传递,并且因此它们的实际类型被推断为具有identity来自当前TU的)。

IOW:您可以通过专门化一些特性来轻松定义自己的占位符,并且它们仍然应该像魅力一样工作。

namespace boost 
{ 
    template<int I> struct is_placeholder< 
      my_funny_own_placeholder_no_ODR_involved<I> > 
    { 
     enum _vt { value = I }; 
    }; 
} 

我想同样的逻辑可以适用于piecewise_construction(但我没有看太多)。

+0

'问题'是当考虑两个TU时,'f'的相应定义是不同的,因为它们不引用相同的'std :: piecewise_construct'并且使用地址,而不是该值。因此,潜在的ODR违规是每个TU中“f”可能不同。由Johannes链接的讨论中提供了更多信息。 –

+0

@LucDanton:这是一个怎样的问题?它们在不同的未命名的命名空间中只是不同的功能?请注意,我主要是基于关于_1,_2 ...占位符的链接讨论。我将阅读关于分段链接的讨论......稍后 – sehe

+0

'f'不在未命名的名称空间中。如果是的话,你是对的,这不会有问题。 –

相关问题