考虑以下类模板"X"及其部分特化.
template <class ...Types>
struct X {}; // #1
template <class T1>
struct X<T1> {}; // #2
template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3
X<int> x; // #2 or #3 ?
Run Code Online (Sandbox Code Playgroud)
我怀疑X <int>是不明确的.这是因为:
很明显,#2和#3都比#1更专业,现在比较#2和#3.根据14.5.5.2,让我们考虑以下哪个#2'和#3'更专业.
template <class T1>
void f(X<T1>); // #2'
template <class T1, class ...Types>
void f(X<T1, Types...>); // #3'
Run Code Online (Sandbox Code Playgroud)
根据14.8.2.4,第一步是模板参数推导,使用#2'作为参数模板,#3'作为参数模板.给定唯一的参数类型是X <A1>,推导出的T1是A1,而Types是空的.
A = X<A1>, P = X<T1, Types...> => T1 = A1, Types = {}
Run Code Online (Sandbox Code Playgroud)
第二步是使用#3'作为参数模板,使用#2'作为参数模板.鉴于唯一的参数类型是X <A1,Args ...>,根据14.8.2.5/9(注意该段最近由N3281修订),Args被简单地忽略,推断的T1是A1并且参数推断成功.
A = X<A1, Args...>, P = …Run Code Online (Sandbox Code Playgroud) c++ templates template-specialization variadic-templates c++11
std::piecewise_construct在<utility>中定义,因为它已声明,因此具有内部链接constexpr.我想知道std::piecewise_construct在标题中使用是否会违反ODR.例如:
#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)
};
}
Run Code Online (Sandbox Code Playgroud)
#include "a.hpp"
Run Code Online (Sandbox Code Playgroud)
#include "a.hpp"
Run Code Online (Sandbox Code Playgroud)
TU 1中的std::piecewise_constructin表示f与TU 2中的对象不同f.我怀疑f违反了ODR.
N3290(也可能是ISO/IEC 14882:2011)表示以下情况是ODR的例外,在3.2/5中:
如果对象在D的所有定义中具有相同的文字类型,并且该对象使用常量表达式(5.19)初始化,并且值(但不是地址),则名称可以引用具有内部链接或无链接的const对象使用该对象,并且该对象在D的所有定义中具有相同的值;
f满足几乎所有要求,但"使用对象的值(但不是地址)"对我来说似乎很模糊.确实std::piecewise_construct_t没有状态,但是对分段构造函数的std::pair调用涉及调用隐式声明的复制构造函数std::piecewise_construct_t,其参数是const std::piecewise_construct_t &.地址是"用过的",不是吗?
我很困惑. …