C ++ 11从初始化列表到数组参数的隐式转换

时间:2013-06-30 07:52:47

标签: c++ templates c++11 initializer-list

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

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

...

foo({1, 2, 3})

我目前正在运行GCC 4.8。

4 个答案:

答案 0 :(得分:6)

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

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)进行了测试,它们按预期工作。
这是一个在线版本at Stacked-Crooked.但是,此代码无法在Ideone上编译。由于我无法弄清楚在Ideone上传递给编译器的选项,我已经放弃了该网站。


我从@Pavel MinaevHow to emulate C array initialization “int arr[] = { e1, e2, e3, … }” behaviour with std::array?问题的回答中无耻地窃取make_array函数。其他make_array建议导致编译错误,我无法解决。

make_array功能有局限性,请阅读the entire post;特别是关于comp.lang.c ++。moderated的讨论std::array - if only it knew its size被引用。显然,获得合理的make_array非常棘手。 我不建议在此答案中使用简单明了的make_array来在生产代码中使用。


如果大小是std::initializer_list的模板参数,则不会有任何问题。因此问题为Why is the size not a template argument of std::initializer_list?

答案 1 :(得分:3)

显然不是。标准(14.8.2.5)称这是一个非推断的背景;

  

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

     

...

     

未推断的上下文是:

     

...

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

示例:

     

模板&lt; class T&gt; void g(T);
  克({1,2,3}); //错误:没有推断出T

的参数

编辑:如果您只使用std::vector重载来扣除类型 可以使同一事情与initializer_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的大小不是模板参数,我想不出一种方法可以从中推导和转发数组 size initializer_list的方式与类型相同。

答案 2 :(得分:2)

可以直接使用初始化列表来实现该语法。 e.g:

#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) {
  ...

答案 3 :(得分:0)

可以引用原始数组:

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