6

在 C++11 中,是否可以执行类似于以下的操作?

template<typename T, size_t N>
void foo(array<T, N> src) { ... }

...

foo({1, 2, 3})

我目前正在运行 GCC 4.8。

4

4 回答 4

7

的,我设法完成了以下工作(因为您允许类似的事情):

template<typename T, size_t N>
void foo(array<T, N> src) { ... }

...

foo('a', 'b');
foo(1, 2, 3);

方法如下:

#include <array>
#include <iostream>
#include <utility>
using namespace std;

template<typename T, unsigned long N>
void foo(array<T,N> src) { 

  for (auto e : src)
    cout << e << endl;
}

template<class T, class... Tail>
auto make_array(T head, Tail... tail) -> std::array<T, 1 + sizeof...(Tail)>
{
     std::array<T, 1 + sizeof...(Tail)> a = {{ head, tail ... }};
     return a;
}

template<class T, class... Tail> 
void foo(T&& head, Tail&&... values) {

    foo(make_array(std::forward<T>(head), std::forward<Tail>(values)...));
}

int main() {

  foo('a', 'b');

  foo(1, 2, 3);
}

我已经用 gcc 4.7.2 和 clang 3.4 (trunk 184647) 对此进行了测试,它们按预期工作。
这是 Stacked-Crooked 的在线版本但是,此代码无法在 Ideone 编译。由于我无法弄清楚传递给 Ideone 编译器的选项,因此我放弃了该站点。


make_array@Pavel Minaev如何使用 std::array 模拟 C 数组初始化“int arr[] = { e1, e2, e3, ... }” 行为的回答中无耻地窃取了函数?问题。其他make_array建议导致我无法修复的编译错误。

make_array功能有局限性,请阅读全文;特别是讨论std::array - 如果它知道它在 comp.lang.c++.moderated 上的大小被引用。显然,得到一个合理make_array的是相当棘手的。我不建议make_array将此答案中的头脑简单的人用于生产代码。


如果 size 是std::initializer_list. 因此问题为什么大小不是 std::initializer_list 的模板参数?

于 2013-06-30T10:54:40.253 回答
3

显然不是。标准 (14.8.2.5) 将此称为非推断上下文;

然而,在某些情况下,该值不参与类型推导,而是使用在其他地方推导或明确指定的模板参数的值。

...

未推断的上下文是:

...

  • 一个函数形参,其关联实参是一个初始化列表 (8.5.4) 但该形参没有 std::initializer_list 或对可能有 cv 限定的 std::initializer_list 类型的引用。

例子:

模板<class T> void g(T);
g({1,2,3}); // 错误:没有为 T 推导出参数

编辑:如果您只是使用重载来使类型的扣除起作用,您可以使用相同的东西;std::vectorinitializer_list

template<typename T>
  void foo(const std::vector<T>& src) { ...your code here... }
template<typename T>
  void foo(const std::initializer_list<T>& src) { foo(std::vector<T>(src)); }

foo({1,2,3});  // Compiles

...但遗憾的是,由于 的大小initializer_list不是模板参数,我想不出一种方法让它以与类型相同的方式推断和转发数组大小。initializer_list

于 2013-06-30T08:10:28.417 回答
2

可以直接使用初始化列表来实现该语法。例如:

#include <iostream>
#include <initializer_list>

void foo(std::initializer_list<int> il) {
  for (auto i: il)
    std::cout << i < std::endl;
}

int main() {
  foo({1,2,3});
}

或使其更通用:

template <typename T>
void foo(std::initializer_list<T> il) {
  ...
于 2013-06-30T08:54:36.600 回答
1

对原始数组的引用是可能的:

template <typename T, size_t N>
void foo(T const (&x)[N]) {
    // x is [1, 2, 3], N = 3
}

int main() {
    foo({1, 2, 3});
    return 0;
}

请注意,必须声明数组const

于 2020-11-27T10:59:45.780 回答