标签: initializer-list

初始化包含自身向量的结构

我有一个菜单系统,我想从常量数据初始化.A MenuItem可以包含作为子菜单的向量MenuItems.但它只能达到一定程度.以下是问题的根本原因:

#include <vector>
struct S { std::vector<S> v ; } ;

S s1 = { } ;
S s2 = { { } } ;
S s3 = { { { } } } ;
Run Code Online (Sandbox Code Playgroud)

g++ -std=c++0x(版本4.4.5)应对s1s2,但s3回来:

prog.cpp:6:22: error: template argument 1 is invalid
Run Code Online (Sandbox Code Playgroud)

(见ideone).难道我做错了什么?

c++ stl initializer-list incomplete-type c++11

11
推荐指数
2
解决办法
1863
查看次数

为什么这被认为是扩展的初始化列表?

#include <vector>

struct foo {
    int i;
    int j;
    int k;
};

int main() {
    std::vector<foo> v(1);
    v[0] = {0, 0, 0};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用g ++编译时,我收到以下警告:

警告:扩展初始化列表仅在-std = c ++ 0x或-std = gnu ++ 0x [默认启用]时可用

据我所知,它只是一个普通的初始化列表.结构是POD类型.

这是一个错误还是我错过了什么?

c++ initializer-list

11
推荐指数
2
解决办法
1万
查看次数

无法使用统一初始化复制std :: vector <std :: function <void()>>.它是否正确?

以下代码无法在GCC 4.7.2或Clang 3.2中编译:

#include <vector>
#include <functional>

int main()
{
   std::vector<std::function<void()>> a;
   std::vector<std::function<void()>> b{a};
}
Run Code Online (Sandbox Code Playgroud)

问题是编译器将尝试使用initializer_list创建b,显然它应该只是调用复制构造函数.然而,这似乎是期望的行为,因为标准表明initializer_list构造函数应该优先.

这段代码适用于其他std :: vector,但对于std :: function,编译器无法知道你是否需要initializer_list构造函数或其他构造函数.

它似乎没有办法解决它,如果是这种情况,那么你永远不能在模板化代码中使用统一初始化.这将是一个巨大的耻辱.

另一方面,Visual Studio(2012年11月CTP)并没有抱怨这一点.但是此时initializer_list支持不是很好,所以它可能是一个bug.

c++ initializer-list c++11

11
推荐指数
2
解决办法
407
查看次数

对于构造函数,如何在variadic-templates和std :: initializer_list之间进行选择?

在c ++ 11的当前状态(比如gcc 4.7.2)中,我应该如何选择使用variadic-template还是std::initializer_list需要可以接受变量参数的构造函数?

c++ templates initializer-list variadic-templates c++11

11
推荐指数
1
解决办法
5792
查看次数

传递初始化列表或容器,看向移动语义?

编辑:在我们开始之前,这个问题不是关于正确使用std::initializer_list; 它是关于在需要方便的语法时应该传递什么.谢谢你坚持主题.


C++ 11引入std::initializer_list了定义接受braced-init-list参数的函数.

struct bar {
    bar( char const * );
    bar( int );
} dog( 42 );

fn foo( std::initializer_list< bar > args );

foo( { "blah", 3, dog } );
Run Code Online (Sandbox Code Playgroud)

语法很好,但由于各种问题,它很糟糕:

  • 他们无法有意义地感动.上述功能必须dog从列表中复制; 这不能转换为移动建筑或省略.仅移动类型根本无法使用.(好吧,const_cast实际上是一个有效的解决方法.如果有一篇关于这样做的文章,我希望看到它.)

  • 也没有constexpr语义.(这在C++ 1y即将发布.但这是一个小问题.)

  • const不像其他地方那样传播; 的initializer_list是从来没有const,但它的内容始终是.(因为它不拥有其内容,所以它不能对副本进行写访问,尽管将它复制到任何地方都很少是安全的.)

  • initializer_list对象不拥有其存储(yikes); 它与提供存储的完全独立的裸阵列(yikes)的关系被隐含地定义(yikes)作为引用与绑定临时(四倍yikes)的关系.

我相信这些事情会在适当的时候得到解决,但是现在是否有最佳实践来获得没有硬编码的优势initializer_list?是否有关于直接依赖它的文献或分析?

显而易见的解决方案是通过值传递标准容器,例如std::vector.一旦将对象从中复制到其中initializer_list,它就会被移动构造为按值传递,然后您可以移出内容.改进是在堆栈上提供存储.一个好的图书馆也许能提供大部分的优点initializer_list,arrayvector,甚至不需要使用前者.

有资源吗?

c++ initializer-list c++11

11
推荐指数
1
解决办法
3427
查看次数

为什么采用std :: initializer_list的构造函数不是双花括号语法的首选

统一初始化是一个重要且有用的C++ 11特性.但是,您不能{}随处使用,因为:

std::vector<int> a(10, 0);    // 10 elements of value zero
std::vector<int> b({10, 0});  // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0};    // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively

auto e(0);    // deduced type is int
auto f = 0;   // deduced type is int
auto g{0};    // deduced type is std::initializer_list<int>
auto h = {0}; // …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list uniform-initialization c++11

11
推荐指数
2
解决办法
4203
查看次数

转发初始化列表表达式

初始化列表表达式非常便于初始化C++容器:

std::vector<int>({1, 2, 3})
Run Code Online (Sandbox Code Playgroud)

......但似乎一个括号内的初始化列表表达式,如{1,2,3}绑定到需要的功能std::initializer_list<int>-它并不似乎绑定到一个通用(转发)参考:

template <class T>
void foo(T&& v)
{
  std::vector<int>(std::forward<T>(v));
}

int main()
{
  foo({1, 2, 3})
}
Run Code Online (Sandbox Code Playgroud)

这输出:

test2.cpp:11:6: note: template<class U> void foo(U&&)
test2.cpp:11:6: note:   template argument deduction/substitution failed:
test2.cpp:33:13: note:   couldn't deduce template parameter ‘U’
Run Code Online (Sandbox Code Playgroud)

(这是GCC 4.7.2的结果.)

遗憾的是,这意味着我们无法转发初始化列表表达式.既然这样做很方便,我想问为什么这不起作用?为什么括号封闭的初始化列表表达式不能绑定到转发引用?或者这是允许的,也许我的编译器太老了?

c++ templates initializer-list c++11

11
推荐指数
2
解决办法
3456
查看次数

是否有任何C++标准的计划来解决初始化列表构造函数的不一致性?

C++中的初始化列表构造函数经常会引起麻烦; 例如

using std::vector;
using std::string;
vector<string> v{3}; // vector of three empty strings
vector<int> u{3}; // vector of one element with value 3
Run Code Online (Sandbox Code Playgroud)

(只是为了澄清,我的意思是<int>构造函数是一个初始化列表构造函数,而<string>一个不是.)

int案例与初始化列表构造函数匹配,而string案例则不匹配.这有点难看,常常会造成麻烦.在Scott Meyers的Effective Modern C++的早期章节(第7项)中也注意到了这一点,他将其描述为标准中有些令人不快的部分,每当初始化列表构造函数可用时,编译器将跳过箍尝试匹配它,优先于每个其他构造函数.

当然,int case可以通过改变u{3}来轻松修复u(3),但这不是重点.

这是理想的行为吗?C++标准委员会是否有任何讨论或计划来解决这种模糊/不愉快?一个例子是要求初始化程序列表构造函数被调用,如下所示:vector<int> u({3})这已经是合法的.

c++ constructor initializer-list c++-standard-library c++11

11
推荐指数
1
解决办法
375
查看次数

为什么std :: initializer_list转换不是首选?

请考虑以下代码段:

#include <iostream>
#include <vector>

void f(std::vector<int>){std::cout << __PRETTY_FUNCTION__ << '\n';}
void f(int x){std::cout << __PRETTY_FUNCTION__ << '\n';}

int main() 
{
    f({42});
}
Run Code Online (Sandbox Code Playgroud)

Live on Coliru

如果你运行它,你可以看到f(int)重载是首选,即使std::vector有一个std::initializer_list构造函数(见#8).

问题:为什么转换{42}int首选(而不是转换为std::vector,{42}std::initializer_list)?

c++ initializer-list overload-resolution c++11

11
推荐指数
1
解决办法
229
查看次数

采用 std::initializer_list 的构造函数优于其他构造函数

我用带有标志的 GCC 11.1.0 编译下面的代码-std=c++17。它发生在标准输出上打印initializer_list

我用带有标志的 MSVC 编译了相同的代码,-std=c++17但它打印了“复制构造函数”。哪个编译器更符合cpp标准?编译器可以自由选择构造函数之一吗?

#include <iostream>
using namespace std;

struct S
{
    S(int) { }
    S(initializer_list<int>) { cout << "initializer_list"; }
    S(const S&) { cout << "copy constructor"; }

    operator int() const { return 1; };
};

int main()
{
    S s1(20);
    S s2{ s1 };
}
Run Code Online (Sandbox Code Playgroud)

c++ constructor initializer-list language-lawyer c++17

11
推荐指数
1
解决办法
281
查看次数