Ada*_*dam 7 c++ initializer-list template-argument-deduction c++17 c++20
之前有人问过,但我很想知道新的C++标准是否有任何改变.任何当前或未来的标准都是可以接受
问:无论如何都要创建一个可以用braced-init-list初始化的Array类,而不必手动指定数组长度,元素存储在堆栈中,并且不需要'make_array'函数.
template<class T, size_t N>
struct Array
{
T items[N];
};
Array<int> foo = { 1, 2, 3 };
Run Code Online (Sandbox Code Playgroud)
由于initializer_list没有模板的大小,使用它的构造函数将无法完成这项工作.C++ 17中的演绎指南几乎可以工作,但您必须省略类型参数,并且所有项目必须具有完全相同的类型
Array foo = { 1, 2, 3 }; // Works
Array<int> foo = { 1, 2, 3 }; // Doesn't work
Array foo = { 1.0, 2.0, 3.0f }; //Doesn't work
Run Code Online (Sandbox Code Playgroud)
采用c数组的构造函数似乎不起作用,因为它initializer_list不会转换为c数组.
是braced-init-list要T[N]在发生int foo[] = { 1, 2, 3 };纯粹的编译器魔术不能在代码被复制?
编辑:这个问题的精神是关于上面的确切语法.没有make_array,没有额外的模板参数,显式项类型,没有双括号,没有动态分配.如果一个普通的数组需要一堆现代的C++ tomfoolery并且仍然无法支持标准语法,那么在我看来这只是一个糟糕的工程权衡.
通过使用显式推导指南,您可以解决列表中所有类型的需求:
template <class... T>
Array(T&&... t) -> Array<std::common_type_t<T...>, sizeof...(T)>;
Array foo = { 1.0, 2.0, 3.0f }; // Deduces Array<double,3u>
Run Code Online (Sandbox Code Playgroud)
我讨厌成为坏消息的承载者,但我相信在当前(至少从C++ 17开始),你的问题的答案是"不",没有办法满足你所有的要求.也就是说,这里发布的解决方案已经接近,但是它们在一个或多个要求中都达不到要求.
我也怀疑在不久的将来答案仍然是"不".并不是说我是先知,但最后几个C++版本的方向似乎暗示一个make_array解决方案更可能是添加的而不是更直接的语言支持.
说明
请允许我更详细地解释一下原因.
首先考虑C++ 17演绎指南.我不会详细介绍它们,因为这个问题的其他答案会对它们进行适当的讨论.他们确实非常接近你的要求,但似乎在某种程度上不尽如人意.(虽然@ max66的答案似乎满足了你的所有要求,除了额外的括号.如果他的语法实际上有效,你可能想要将答案视为"足够接近".)
接下来考虑变量模板解决方案.为了自动确定N,您需要一系列重载函数(基本上只有一个参数和一个参数,其中一个参数和其他变量模板).但这基本上等同于某种形式,make_array所以它也不算数.
最后,我能看到的唯一其他选项将基于initializer_list.问题是如何从该列表中确定N. 在C++ 11日以来到列表的大小的唯一途径是,这将是显然是不可能的const,而不是constexpr.但是,从C++ 14开始,这个size()方法实际上constexpr是你认为至少在理论上可以让编译器根据它来推断N. 不幸的是,为了做到这一点,你需要将N(模板参数)默认为类构造函数(初始化列表)中的某个值.我无法确定以目前的语言形式这样做的任何方法.
我认为未来的版本如何支持这一点
支持这种方法的一种方法是遵循其他语言的示例并添加直接语言支持,将语法桥接到某些类.但这实际上使一些类"特殊".考虑Swift中的以下行:
let ar = [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
在此示例中ar是该类型的对象Array<Int>.但这是通过直接编译器支持完成的,即"数组"是一种特殊情况.无论你做什么,你都不能编写一个执行相同方式的MyArray类(除了让MyArray接受一个数组作为构造选项).C++标准当然可以扩展为类似的东西,但C++倾向于试图避免那些"特殊"的情况.此外,可以提出一个论点
auto ar = make_array(1, 2, 3, 4);
Run Code Online (Sandbox Code Playgroud)
实际上是一个更清晰的意图表示,而不是如下所示:(建议字符'A'将其与初始化列表区分开来)
auto ar = A{ 1, 2, 3, 4 };
Run Code Online (Sandbox Code Playgroud)
另一种更符合当前C++语法的方法是将N参数添加到initializer_list模板类中.毕竟size()现在constexpr是大小必须在编译时知道,那么为什么不将它作为模板参数提供呢?它可以适当默认值,以便可以很少需要它,但它会允许类(包括标准的像std::array和自定义的像你这样的提议)在搭售的N个的可能性Array模板到N的initializer_list.那么你应该能够写出以下几行:
template<class T, size_t N>
struct Array
{
explicit Array(std::initializer_list<N> il);
}
Run Code Online (Sandbox Code Playgroud)
当然,诀窍initializer_list是以一种不破坏现有代码的方式进行这种改变.
我怀疑标准委员会不会遵循这些途径,但更有可能添加实验make_array方法.而且我不相信这是个坏主意.我们习惯于make_...语言的许多其他部分,为什么不在这里呢?
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |