std::array
的推导指南要求所有类型都相同:
std::array arr = { 1, 2, 3.4 }; // error
此要求背后的原理是什么?如果允许使用不同类型的产品,会不会有明显的弊端?例如:
namespace std {
template <typename... T>
array(T...) -> array<std::common_type_t<T...>, sizeof...(T)>;
}
std::array arr = { 1, 2, 3.4 }; // decltype(arr)::value_type deduced as double
答案 0 :(得分:10)
有substantial design issues个正在使用common_type
。例如,std::common_type_t<A, B, C>
,std::common_type_t<C, A, B>
和std::common_type_t<C, B, A>
不必全部都存在-如果存在,则不必是同一类型:
struct A;
struct B;
struct C;
struct A { operator B(); };
struct B { operator C(); };
struct C { operator A(); };
static_assert(std::is_same_v<std::common_type_t<A, B, C>, C>);
static_assert(std::is_same_v<std::common_type_t<C, A, B>, B>);
static_assert(std::is_same_v<std::common_type_t<C, B, A>, A>);
在对初始化器的元素进行重新排序时,会导致“有趣的”用户体验,从而推论出不同的类型(或发出错误)。
答案 1 :(得分:6)
它与函数模板参数的推导方式匹配。
如果它们产生的推导次数多于一个
for(let key in document){ let isEnumerable = document.propertyIsEnumerable(key); console.log(`docment['${key}'] isEnumerable?:${isEnumerable}`); }
,则类型推导失败。
例如
WWW-Authenticate: NTLM
但是您可以提供常见类型的推导指南。
A
或转发给常见类型的重载
template<typename T>
void foo(T, T){}
template<typename T>
struct bar{ bar(T, T) {} };
int main()
{
foo(1, 1.5); // error, note: deduced conflicting types for parameter 'T' ('int' and 'double')
bar(1, 1.5); // error, note: deduced conflicting types for parameter 'T' ('int' and 'double')
}
答案 2 :(得分:1)
编辑::在下面的评论中,Daniel指出他确实在问,为什么一个单一类型的std::array
不能被包含以下项的列表初始化:不同的类型(例如两个int
和一个double
)。不是为什么std::array
必须是单一类型。
它不能满足Daniel对基本原理的要求,但是某些C ++环境支持实验\ array标头和std::experimental::make_array
类,它们确实允许初始化不同类型的std :: array。可以推导或指定数组类型...
#include <array>
#include <experimental/array>
// creates array of doubles
auto arr = std::experimental::make_array(1, 2, 3.4);
// creates array of ints
auto ra = std::experimental::make_array<int> (1, 2, 3.4);
这种要求背后的原理是什么?
该限制是满足数组容器的语义所必需的。
例如,cppreference就是这样……
此容器是一种聚合类型,其语义与将C样式数组
T[N]
作为其唯一的非静态数据成员的结构相同。
很明显,没有一种类型超过 T 的C样式数组。
从另一个角度来看:cplusplus这样说…
容器属性
序列
顺序容器中的元素按严格的线性顺序排序。各个元素按其在此序列中的位置进行访问。连续存储
元素存储在连续的内存位置中,允许对元素进行恒定时间的随机访问。元素的指针可以偏移以访问其他元素。固定大小的聚合
容器使用隐式构造函数和析构函数静态地分配所需的空间。它的大小是编译时常数。没有内存或时间开销。
为使指针运算有意义,每个元素必须具有相同的宽度。为了使指针更有意义(在指针算术之后),每个元素必须使用相同的位表示形式-否则,您可能会发现自己将IEEE浮点表示形式视为是二进制补码整数(反之亦然)。>
说“因为标准如此”并不能真正满足您的基本要求,但确实可以(我认为)。我找不到实际标准的可引用副本,但是a working draft of the C++ standard表示了这一点……
26.3.7.2数组构造函数,复制和分配[array.cons]
合计(11.6.1)的条件应得到满足。类数组依赖于隐式声明的特殊成员函数(15.1、15.4和15.8),以符合26.2中的容器要求表。除了容器需求表中指定的需求之外,数组的隐式move构造函数和move赋值运算符还分别要求T为MoveConstructible或MoveAssignable。template<class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>;`
要求:
(is_same_v<T, U> && ...)
是正确的。否则程序格式错误。