使用带有使用constexpr递归定义的类型的C++11 initializer_list
Using a C++11 initializer_list with a recursively defined type using 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<3> a={1,2,3}。如果initializer_list
中有一个constexpr tail
函数,我认为它应该可以工作。
是的,以一种迂回的方式,有效地将初始值设定项列表拆包并重新打包为更合适的格式。然而,还有一种更好的(imho)方法:变分模板。
#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
作为基本情况,因为它更有意义。
我没有编译器可以编译它,但我认为正确的答案是:
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;
};
对于递归结构,初始值设定项列表必须递归地传递给采用迭代器的构造函数。
解决方案是创建一个名为的函数
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一起工作,而不与其他任何东西一起测试。就规则而言,这可能是不正确的。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- C++中带有List类的迭代器Segfault
- 使用"std::unordereded_map"映射到"std::list"对象
- GCC对可能有效的代码抛出init list生存期警告
- MSVC是否支持C++11样式的属性而不是__declspec
- 创建LinkedList退出,返回代码为-11(SIGSEGV)
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 使用std::list创建循环链表
- 如何将模板转换为C++11之前的模板
- 重载Singly Linked List中的赋值运算符
- C++11 基于范围的 for 循环,用于 std::list
- c++11移动std::deque或std::list的插入
- C++11线程修改std::list
- 为什么 std::list 在 C++11 上更大
- 使用c++ 11 Lambda函数更改vector(list, deque…)中的所有元素
- 为什么 gcc 4.8.1 给我">> should be > > within a nested templated list"错误?这不是在 C++11 中修复的吗?
- 是否有可能在c++11中为每个循环擦除std::list中的元素?