使用带有递归定义类型的C ++ 11 initializer_list,使用constexpr

时间:2012-03-13 00:00:13

标签: c++ c++11 initializer-list recursive-datastructures constexpr

是否可以使用C ++ 11 initializer_list使用Foo构造函数汇编下面的constexpr递归定义的类:

template <size_t N>
struct Foo {
  constexpr Foo(int x, Foo<N-1> f) : x(x), xs(xs) {}
  int x;
  Foo<N-1> xs;
};

template <> struct Foo<0> {};

我可以使用

初始化Foo<3>
int main(int argc, char *argv[])
{
  Foo<3> a = Foo<3>(1,Foo<2>(2,Foo<1>(3,Foo<0>())));
  return 0;
}

使用Foo&lt; 3&gt;会很好。 a = {1,2,3}而不是。如果constexpr tail中有initializer_list函数,我认为它应该有用。

3 个答案:

答案 0 :(得分:9)

是的,以一种循环方式,有效地解压缩并将初始化列表重新打包为更合适的格式。但是,有一种更好的(imho)方式:Variadic模板。

#include <stddef.h>
#include <iostream>

template <size_t N>
struct Foo {
  template<class... Tail>
  constexpr Foo(int i, Tail... t) : x(i), xs(t...) {}

  void print(){
    std::cout << "(" << x << ", ";
    xs.print();
    std::cout << ")";
  }

  int x;
  Foo<N-1> xs;
};

template <> 
struct Foo<1> {
  constexpr Foo(int i) : x(i) {}
  void print(){ std::cout << "(" << x << ")"; }
  int x;
};

int main(){
 Foo<3> x = {1, 2, 3};
 x.print();
 std::cout << "\n";
}

按预期输出:

  

(1,(2,(3)))

请注意,我选择1作为基本情况,因为它更有意义。

答案 1 :(得分:1)

我没有可编译它的编译器,但我认为正确的答案是:

template <size_t N>
struct Foo {
  constexpr Foo(int x, Foo<N-1> f)   //template iterator constructor
  : x(x), xs(xs) {}
  Foo(std::initializer_list<int> f)  //initializer list constructor
  : x(*f.begin()), xs(++f.begin(), f.end()) 
  { static_assert(xs.size()==N, "incorrect number of values in initializer list");}
  template<class iter>
  Foo(iter first, iter last)  //template iterator constructor
  : x(*first), xs(++first, last) {}  //UB if wrong number of values given

  int x;
  Foo<N-1> xs;
};

template <> 
struct Foo<1> { //I use 1 for smaller structures
  constexpr Foo(int f) 
  : x(f) {}
  Foo(std::initializer_list<int> f) 
  : x(*f.begin())
  { static_assert(xs.size()==1, "incorrect number of values in initializer list");}
  template<class iter>
  Foo(iter first, iter last)
  : x(*first)
  { assert(first+1 == last); } 

  int x;
};

对于递归结构,初始化程序列表必须以递归方式传递给接收迭代器的构造函数。

答案 2 :(得分:0)

解决方案是创建一个名为

的函数
template<class T>
constexpr T initlist_val(initializer_list<T>& list, int index) {
  return (index < list.size()) ? *(list.begin() + index) : 0;
}

现在你可以去

class MyClass {
public:
  int A, int B;
  constexpr MyClass(const initializer_list<int>& list) : A(initlist_val(list,0)), B(initlist_val(1)) {
  // Put nothing here etc..
  }

};

你不需要所有其他的东西。这可以与未经其他任何测试的GCC一起使用。可能在规则方面不正确。