标签: initializer-list

C++ 初始化列表重载消歧

我有一个关于 C++ 初始化列表消歧的问题,它在 gcc、clang 和 Visual Studio 之间表现出不同的行为。

我想知道这是“未定义的行为”(不正确的程序)还是这些编译器之一有错误。任何的想法?

考虑以下声明:

class Arg
{
public:
    Arg(int i);
};

class Object
{
public:
    Object(const char* str, int i);
    Object(const char* str, const std::initializer_list<Arg>& args);
};
Run Code Online (Sandbox Code Playgroud)

现在这种用法:

Object c("c", {4});
Run Code Online (Sandbox Code Playgroud)

应该使用哪个构造函数?一个 with int(假设文字周围的大括号是多余的)或一个带有初始化列表的(隐式转换 from intto Arg)。

GCC 10.2.0 选择具有初始化列表的构造函数Arg

Clang 11.2.2-2 选择构造函数int并报告有关大括号的警告:

initlist.cpp:46:19: warning: braces around scalar initializer [-Wbraced-scalar-init]
    Object c("c", {4});
                  ^~~
Run Code Online (Sandbox Code Playgroud)

Visual Studio 2019 16.8.6 选择int没有警告的构造函数( /W4)。

从多数人的角度来看,具有int胜利的构造函数。另一方面,如果我们直接使用std::initializer_list<int> …

c++ initializer-list compiler-bug

10
推荐指数
1
解决办法
161
查看次数

递归使用时 std::initializer_list 的生命周期

我正在尝试使用它std::initializer_list来定义和输出递归数据结构。在下面的示例中,我正在处理一个列表,其中每个元素可以是整数,也可以是同一类型列表的另一个实例。我使用中间变体类型来执行此操作,该中间变体类型可以是初始值设定项列表或整数。

我不清楚的是,它的生命周期是否std::initializer_list足够长来支持这个用例,或者我是否会遇到内存访问不一致的可能性。代码运行良好,但我担心这不能得到保证。我的希望是,用于创建最顶层列表的std::initializer_list任何中间临时std::initializer_list对象仅在顶层表达式完成后才被清除。

struct wrapped {
    bool has_list;
    int n = 0;
    std::initializer_list<wrapped> lst;

    wrapped(int n_) : has_list(false), n(n_) {}
    wrapped(std::initializer_list<wrapped> lst_) : has_list(true), lst(lst_) {}

    void output() const {
      if (!has_list) {
        std::cout << n << ' ';
      } else {
        std::cout << "[ ";
        for (auto&& x : lst)  x.output();
        std::cout << "] ";
      }
    }
  };

  void call_it(wrapped w) {
    w.output();
    std::cout << std::endl;
  }

  void call_it() {
    call_it({1});                 // …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list language-lawyer

10
推荐指数
1
解决办法
202
查看次数

C++:struct/class中的构造函数与初始化列表

可以使用初始化列表创建结构/类的对象(没有构造函数).为什么在构造函数的 struct/class上不允许这样做?

struct r { int a; };
struct s { int a; s() : a(0) {} };
r = { 1 }; // works
s = { 1 }; // does not work
Run Code Online (Sandbox Code Playgroud)

c++ constructor struct class initializer-list

9
推荐指数
1
解决办法
3725
查看次数

c ++ initializer_list和shared_ptr行为

我正在测试vs2013 c ++ initializer_list.

可以编译下面的代码.但是当我运行exe时崩溃了.

#include <memory>
#include <iostream>

class Base {};

class Derived : public Base {};

void DoSomething(std::initializer_list<std::shared_ptr<Base> > list)
{
}

int main()
{
  auto ip = std::make_shared<Derived>();

  std::cout << "use_count=" << ip.use_count() << std::endl;

  DoSomething({ip, std::make_shared<Derived>()}); // ng
  // DoSomething({ip, std::make_shared<Base>()}); // ok
  // DoSomething({std::make_shared<Derived>(), ip}); // ok

  std::cout << "use_count=" << ip.use_count() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

编译.

C:\...>cl.exe /EHsc test.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list visual-studio-2013

9
推荐指数
1
解决办法
1671
查看次数

什么语言规则允许C++ 11推断出这是对的initializer_list?

在C++ 11中,初始化a似乎是合法的std::map<std::string, int>,如下所示:

std::map<std::string, int> myMap = {
     { "One",   1 },
     { "Two",   2 },
     { "Three", 3 }
};
Run Code Online (Sandbox Code Playgroud)

直观地看,这是有道理的-在括号内的初始化是对串的名单,并std::map<std::string, int>::value_typestd::pair<std::string, int>(可能有一些const资质.

但是,我不确定我是否理解这里的打字工作方式.如果我们在这里消除变量声明并且只是使用大括号括起初始化器,编译器就不会知道它正在查看a,std::initializer_list<std::pair<std::string, int>>因为它不知道被支撑的对代表std::pairs.因此,似乎编译器以某种方式推迟将类型赋值给括号封闭的初始化器,直到它从std::map构造函数中获得足够的类型信息来实现嵌套大括号用于对.我不记得在C++ 03中发生过这样的事情; 据我所知,表达式的类型从不依赖于它的上下文.

哪些语言规则允许此代码正确编译,以及编译器确定用于初始化列表的类型?我希望能够获得有关C++ 11规范的具体参考的答案,因为它的确很有意义!

谢谢!

c++ initializer-list language-lawyer c++11 list-initialization

9
推荐指数
1
解决办法
362
查看次数

是否可以使用operator new和initialiser语法初始化非POD数组?

我刚刚阅读并了解是否可以使用new运算符初始化C++ 11中的数组,但它并没有完全解决我的问题.

这段代码在Clang中给出了一个编译错误:

struct A
{
   A(int first, int second) {}
};
void myFunc()
{
   new A[1] {{1, 2}};
}
Run Code Online (Sandbox Code Playgroud)

我期望{{1,2}}使用单个元素初始化数组,然后使用构造函数args {1,2}初始化,但是我收到此错误:

error: no matching constructor for initialization of 'A'
   new A[1] {{1, 2}};
            ^
note: candidate constructor not viable: requires 2 arguments, but 0 were provided
   A(int first, int second) {}
   ^
note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
struct A
       ^
Run Code Online (Sandbox Code Playgroud)

为什么这种语法不起作用?

c++ arrays clang initializer-list c++11

9
推荐指数
1
解决办法
328
查看次数

推断容器和initializer_list-s的模板函数

我想编写一个辅助函数,如:

template <typename F, typename Range1, typename Range2>
auto helper(const Range1& left, const Range2& right, F&& pred)
{
    using namespace std; // for cbegin/cend and ADL
    return pred(cbegin(left), cend(left), cbegin(right), cend(right));
}
Run Code Online (Sandbox Code Playgroud)

它适用于容器:

std::vector<int> v1 = {1,2,3,4,5,6};
std::vector<int> v2 = {5,4,3,2,1,6};

std::cout << helper(v1, v2, [](const auto&... args){ return std::is_permutation(args...);}) << std::endl;
Run Code Online (Sandbox Code Playgroud)

但它没有推断initializer_list--s(例子):

std::cout << helper({1,2,3,4,5,6}, {5,4,3,2,1,6}, [](const auto&... args){ return std::is_permutation(args...);}) << std::endl;
Run Code Online (Sandbox Code Playgroud)

是否有一种惯用的重写方式,helper以便它推导出容器和initializer_list-s?

对于容器和容器的所有组合,initializer_list我无法想出任何比重更好的东西.

c++ templates initializer-list c++14 c++17

9
推荐指数
1
解决办法
199
查看次数

C++ 复制构造函数:我必须拼写出初始值设定项列表中的所有成员变量吗?

我有一些非常复杂的物体。它们包含其他对象的成员变量。我理解复制构造函数级联的美妙之处,这样默认的复制构造函数通常就可以工作。但是,最常破坏默认复制构造函数的情况(对象包含一些成员变量,它们是指向其其他成员变量的指针)仍然适用于我构建的很多内容。这是我的一个对象、它的构造函数和我编写的复制构造函数的示例:

struct PhaseSpace {
  PhaseSpace();

private:
  std::string file_name;              ///< Name of the file from which these coordinates (and
                                      ///<   perhaps velocities) derived.  Empty string indicates
                                      ///<   no file.
  int atom_count;                     ///< The number of atoms in the system
  UnitCellType unit_cell;             ///< The type of unit cell
  Hybrid<double> x_coordinates;       ///< Cartesian X coordinates of all particles
  Hybrid<double> y_coordinates;       ///< Cartesian Y coordinates of all particles
  Hybrid<double> z_coordinates;       ///< Cartesian Z coordinates of all particles
  Hybrid<double> box_space_transform; ///< Matrix to transform coordinates …
Run Code Online (Sandbox Code Playgroud)

c++ copy-constructor initializer-list

9
推荐指数
1
解决办法
1594
查看次数

std::initializer_list 中两个构造函数之间的重载解析

在下面的程序中,structC有两个构造函数:一个来自std::initializer_list<A>,另一个来自std::initializer_list<B>。然后使用以下命令创建该结构的对象C{{1}}

#include <initializer_list>

struct A {
    int i;
};

struct B {
    constexpr explicit B(int) {}
};

struct C {
    int v;
    constexpr C(std::initializer_list<A>) : v(1) {}
    constexpr C(std::initializer_list<B>) : v(2) {}
};

static_assert( C{{1}}.v == 1 );
Run Code Online (Sandbox Code Playgroud)

由于只能A从 隐式构造聚合int,因此可以预期这C(std::initializer_list<A>)是首选并且程序成功。在 Clang 中确实如此。

然而海湾合作委员会抱怨:

error: call of overloaded 'C(<brace-enclosed initializer list>)' is ambiguous
note: candidate: 'constexpr C::C(std::initializer_list<B>)'
note: candidate: 'constexpr C::C(std::initializer_list<A>)'
Run Code Online (Sandbox Code Playgroud)

MSVC 也是如此:

error C2440: '<function-style-cast>': cannot …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list language-lawyer overload-resolution

9
推荐指数
1
解决办法
190
查看次数

无法从initializer_list移动​​的解决方法?

方便的initializer_list语法似乎是以无法移动列表成员、创建不必要的副本为代价的。

struct  A
{
    // some members which are dynamic resources...
    A() { cout << "Default Constructor\n"; }
    A(const A& original) { cout << "Copy constructor\n"; }
    A(A&& original) { cout << "Move constructor\n";  }
};
    
int main() {
    vector<A> v1{ A() , A() }; // calls copy
    vector<A> v2;
    v2.push_back(A()); v2.push_back(A()); // calls move
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,这是因为取消引用初始化器迭代器会给出const T,即使尝试移动时也会复制它。

有解决方法吗?

阅读/sf/answers/3101541901/,提出了一种使用可变参数模板的解决方案,如下所示:

template<class Array> struct maker;

// a maker which makes a std::vector
template<class …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list move-semantics c++20 c++23

9
推荐指数
1
解决办法
306
查看次数