标签: list-initialization

您可以使用花括号初始化列表作为(默认)模板参数吗?

我需要定义一个接受多个 3D 坐标作为参数的 C++ 模板。当这些坐标的所有维度都定义为单独的整数变量时,参数列表将变得非常长 - 3 个坐标需要 9 个参数,这使得模板难以使用。

因此,非常希望以使用编译时数组的方式声明模板。它们的默认参数也应该直接在模板声明的位置声明为值,而不是变量名。

经过一些实验,令我惊讶的是,我发现 GCC 13 将接受以下 C++ 程序std=c++20

#include <cstdio>
#include <array>

template <
    std::array<int, 3> offset = {0, 0, 0}
>
struct Array
{
    void operator() (int i, int j, int k) 
    {
        printf("(%d, %d, %d)\n", i + offset[0], j + offset[1], k + offset[2]);
    }
};

int main(void)
{
    Array arr_default;
    arr_default(0, 0, 0);

    Array<{1, 1, 1}> arr;
    arr(0, 0, 0);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然而,clang 18 拒绝使用 …

c++ language-lawyer list-initialization braced-init-list c++-templates

15
推荐指数
1
解决办法
660
查看次数

为什么variadic函数不能"吃掉"C++ 11中的list-initialization参数?

示例代码是:

#include <unordered_map>

int main() {
    std::unordered_map<int, std::pair<int, int>> map;

    map.emplace(1, {1, 1});

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

哪里emplace()有签名,如:

template <class... _Args>
pair<iterator, bool> emplace(_Args&&... __args);
Run Code Online (Sandbox Code Playgroud)

gcc说的功能expectes 0参数- 2提供的.该clang说,函数需要1个参数- 2提供的.

我甚至不明白 - 这段代码有什么问题?

c++ variadic-functions compiler-bug c++11 list-initialization

14
推荐指数
2
解决办法
506
查看次数

我可以使用C++ 11大括号初始化语法来避免为简单聚合声明普通构造函数吗?

假设我有以下代码:

#include <vector>

struct Foo
{
    int tag = 0;
    std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
}
Run Code Online (Sandbox Code Playgroud)

现在我想要Foo使用特定的向量向量添加新项目,tagcode 不是明确创建临时项目.这意味着我必须添加一个构造函数Foo:

struct Foo
{
    inline Foo(int t, std::function<void ()> c): tag(t), code(c) {}

    int tag = 0;
    std::function<void ()> code;
};
Run Code Online (Sandbox Code Playgroud)

现在我可以使用emplace_back:

v.emplace_back(0, [](){});
Run Code Online (Sandbox Code Playgroud)

但是当我不得不再次这样做 - 第100次 - 使用新创建的结构时,我想:我不能使用大括号初始化器吗?像这样:

#include <vector>

struct Foo
{
   int tag = 0;
   std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
   v.push_back(Foo{ 0, …
Run Code Online (Sandbox Code Playgroud)

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

14
推荐指数
2
解决办法
1577
查看次数

复制形式'= {}'的初始化

鉴于以下内容:

#include <stdio.h>

class X;

class Y
{
public:
  Y() { printf("  1\n"); }             // 1
  // operator X(); // 2
};

class X
{
public:
  X(int) {}
  X(const Y& rhs) { printf("  3\n"); } // 3
  X(Y&& rhs) { printf("  4\n"); }      // 4
};

// Y::operator X() { printf("   operator X() - 2\n"); return X{2}; }

int main()
{
  Y y{};     // Calls (1)

  printf("j\n");
  X j{y};    // Calls (3)
  printf("k\n");
  X k = {y}; // Calls (3) …
Run Code Online (Sandbox Code Playgroud)

c++ copy-initialization c++11 list-initialization c++14

14
推荐指数
1
解决办法
428
查看次数

我可以通过元素的完美转发来列表初始化 std::vector 吗?

我注意到当移动更适用时,std::vector 的聚合 列表初始化执行复制初始化。同时,多个 emplace_backs 做我想做的。

我只能想出这个编写模板函数的不完美解决方案init_emplace_vector。不过,它仅适用于非显式单值构造函数。

template <typename T, typename... Args>
std::vector<T> init_emplace_vector(Args&&... args)
{
  std::vector<T> vec;
  vec.reserve(sizeof...(Args));  // by suggestion from user: eerorika
  (vec.emplace_back(std::forward<Args>(args)), ...);  // C++17
  return vec;
}
Run Code Online (Sandbox Code Playgroud)

我真的需要使用 emplace_back来尽可能有效地初始化 std::vector 吗?

// an integer passed to large is actually the size of the resource
std::vector<large> v_init {
  1000,  // instance of class "large" is copied
  1001,  // copied
  1002,  // copied
};

std::vector<large> …
Run Code Online (Sandbox Code Playgroud)

c++ vector perfect-forwarding c++11 list-initialization

14
推荐指数
1
解决办法
283
查看次数

哪些贪婪的初始化列表示例潜伏在标准库中?

从C++ 11开始,标准库容器和std::string构造函数都采用初始化列表.这个构造函数优先于其他构造函数(甚至,正如@ JohannesSchaub-litb在评论中指出的那样,甚至忽略了其他"最佳匹配"标准).当将所有带括号()的构造函数转换为其支撑版本时,这会导致一些众所周知的陷阱{}

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>

void print(std::vector<int> const& v)
{
    std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
    std::cout << "\n";
}

void print(std::string const& s)
{
    std::cout << s << "\n";
}

int main()
{
    // well-known 
    print(std::vector<int>{ 11, 22 });  // 11, 22, not 11 copies of 22
    print(std::vector<int>{ 11 });      // 11,     not 11 copies of 0

    // more surprising
    print(std::string{ 65, 'C' });      // AC,     not 65 …
Run Code Online (Sandbox Code Playgroud)

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

13
推荐指数
1
解决办法
991
查看次数

c ++ 11列表初始化的不同行为

请考虑以下代码:

class A {
private:
  std::string s;
public:
  A() = delete;
  A(const A&) = delete;
  A(A&&) = delete;
  A(const std::string &a) : s(a) {}
};
Run Code Online (Sandbox Code Playgroud)

现在,我想初始化一个使用列表初始化的A数组.g ++(4.9.1)可以成功构建以下代码:

int main() {
  A arr[2] = {{"a"}, {"b"}};
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,它失败了以下代码:

class Aggr {
private:
  A arr[2];
public:
  Aggr() : arr{{"a"}, {"b"}} {}
};
Run Code Online (Sandbox Code Playgroud)

错误消息是,

test.cc: In constructor ‘Aggr::Aggr()’:
test.cc:22:28: error: use of deleted function ‘A::A(A&&)’
   Aggr() : arr{{"a"}, {"b"}} {}
                            ^          
test.cc:11:3: note: declared here
   A(A&&) = delete;
   ^
Run Code Online (Sandbox Code Playgroud)

也就是说,list-initializer尝试调用move构造函数来初始化类中的数组.但是,该代码是由clang v3.5成功构建的,没有任何警告.所以,我想知道C++ …

c++ c++11 list-initialization

13
推荐指数
1
解决办法
286
查看次数

使用列表初始化调用Ambigous构造函数

struct A {
    A(int) {}
};

struct B {
    B(A) {}
};

int main() {
    B b({0});
}
Run Code Online (Sandbox Code Playgroud)

构造出现b以下错误:

In function 'int main()':
24:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
24:9: note: candidates are:
11:2: note: B::B(A)
10:8: note: constexpr B::B(const B&)
10:8: note: constexpr B::B(B&&)
Run Code Online (Sandbox Code Playgroud)

我期待B::B(A)被召唤,为什么在这种情况下它是模棱两可的?

c++ c++11 list-initialization

13
推荐指数
1
解决办法
801
查看次数

为什么GCC 6.3在没有明确的C++ 11支持的情况下编译这个Braced-Init-List代码?

我有一个关于卷括号括号列表的不同含义的问题.

我知道C++ 03不支持C++ 11 initializer_list.然而,即使没有-std=c++11编译器标志,gcc 6.3 也会interpolate使用以下代码正确初始化:

map<string, string> interpolate = { { "F", "a && b && c" }, { "H", "p ^ 2 + w" }, { "K", "H > 10 || e < 5" }, { "J", "F && !K" } };
Run Code Online (Sandbox Code Playgroud)

我被问到为什么这会起作用,我意识到我没有答案.这是一个Brace-Init-List,但我们从初始化标准容器的方式通常是通过initializer_list.那么非C++ 11代码如何完成初始化呢?

c++ gcc initializer-list c++03 list-initialization

13
推荐指数
1
解决办法
1450
查看次数

为什么{}工作而while()不在这里初始化原子对象?

考虑一下代码:

#include <atomic>

struct stru {
  int a{};
  int b{};
};

int main() {
  // Doesn't work: std::atomic<stru> as({});
  std::atomic<stru> as{{}};
}
Run Code Online (Sandbox Code Playgroud)

为直接初始化生成的错误消息如下:

prog.cc: In function 'int main()':
prog.cc:9:26: error: call of overloaded 'atomic(<brace-enclosed initializer list>)' is ambiguous
   std::atomic<stru> as({});
                          ^
In file included from prog.cc:1:0:
/opt/wandbox/gcc-7.2.0/include/c++/7.2.0/atomic:200:17: note: candidate: constexpr std::atomic<_Tp>::atomic(_Tp) [with _Tp = stru]
       constexpr atomic(_Tp __i) noexcept : _M_i(__i) { }
                 ^~~~~~
/opt/wandbox/gcc-7.2.0/include/c++/7.2.0/atomic:196:7: note: candidate: std::atomic<_Tp>::atomic(const std::atomic<_Tp>&) [with _Tp = stru] <deleted>
       atomic(const atomic&) = delete;
   ^~~~~~
Run Code Online (Sandbox Code Playgroud)

我认为这两种形式在这种特殊情况下应该没有区别.为什么会这样?

c++ initialization atomic list-initialization c++14

13
推荐指数
0
解决办法
142
查看次数