c++ - 指定初始值设定项中参数列表的大括号数量

标签 c++ initialization c++20

即使我使用 C++2a 指定的初始值设定项,我目前仍在处理参数列表中大括号的数量。

我有一些嵌套结构作为示例:

#include <string>
#include <optional> 

struct Base
{
    std::string name;
};

struct KL: public Base
{
    int p1;
    int p2;
};

struct FFA: public Base
{
    int pp1;
    int pp2;
    int pp3;
};

struct Spur
{
    std::optional< KL >              kl;
    std::optional< FFA >             ffa ;
};

struct Config
{
    std::string s;
    int i1;
    int i2;
    Spur spur;

    Config(
        const std::string& _s,
        int _i1,
        int _i2,
        const Spur& _spur
        ): s{_s},i1{_i1},i2{_i2},spur{_spur}{}
};

class Signal
{
    public:
        Signal( const Config& ) {}
};

struct A { int i; };
struct B { std::string s; };
struct X { A a; B b; };

int main()
    Spur s1{   .kl= {{ "XYZ", 1,2 }}}; // works! gcc+clang but clang warns "suggest braces around initialization of subobject"
    Spur s2{   .kl=  { "XYZ", 1,2 }} ; // fails! could not convert '{"XYZ", 1, 2}' from '<brace-enclosed initializer list>' to 'std::optional<KL>'
    Spur s3{ { .kl=  { "XYZ", 1,2 }}}; // works gcc! clang fails: no matching constructor for initialization of 'std::optional<KL>' 


    Config c1{ "ABC", 1,2 , {{ .kl=std::nullopt }}}; // works gcc, clang fails no matching constructor for initialization of 'Config'
    Config c2{ "ABC", 1,2 , {  .kl=std::nullopt }} ; // works for gcc and clang

    Signal si1{ {"ABC", 1,2 , {{ .kl = std::nullopt     }} }}; // gcc ok, clang fails: no matching constructor for initialization of 'Signal'
    Signal si2{ {"CDE", 3,4 , {{ .kl = KL{ "XYZ", 1,2 } }} }}; // gcc ok, clang fails: no matching constructor for initialization of 'Signal'
    Signal si3{ {"CDE", 3,4 , {{ .kl =   { "XYZ", 1,2 } }} }}; // gcc ok, clang fails: no matching constructor for initialization of 'Signal'
    Signal si4{ {"CDE", 3,4 , {  .kl = KL{ "XYZ", 1,2 }  } }}; // clang & gcc ok
    Signal si5{ {"CDE", 3,4 , {  .kl =   { "XYZ", 1,2 }  } }}; // gcc& clang fail: no matching function for call to 'Signal::Signal(<brace-enclosed initializer list>)'

    X x{ .b={"Hallo"  }}; 
    X x2{ .a={1} };

我的问题是: 当我需要在初始化列表中的参数集周围使用另一组大括号时?

我已经读过Nested braces and designated Initializers

使用的编译器: clang 版本 6.0.1g++ (GCC) 8.2.1 标志:-std=c++20

有人可以解释一下必须满足哪条规则才能消除所有错误和警告吗? ( clang 总是警告缺少大括号,但我找不到应该在哪里设置其他不会破坏 gcc 编译的大括号)。如果能得到一个可以在 gcc 和 clang 上编译的示例就好了。

最佳答案

您可能会使用:

Spur s1{ .kl = {{ {"XYZ"}, 1,2 }}};
Config c1{ "ABC", 1,2 , { .kl = std::nullopt }};
Signal si1{ {"ABC", 1,2 , { .kl = std::nullopt} }};

Demo

您需要 "XYZ" 周围的 {} 来初始化基类。
(您甚至可以再添加一个 {} 来更明确地从 const char* 构建 std::string :-) )

.kl = { { {"XYZ"}, 1,2 } }
      | | |
      | | v
      | | Base
      | v
      | KL
      v
      optional

关于c++ - 指定初始值设定项中参数列表的大括号数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55166799/

相关文章:

c++ - 默认初始化与值初始化

c++ - POD 全局对象初始化

c++ - 概念可以与模板模板参数一起使用吗?

c# - 如何在 C++ 和 C# 之间传递带有空字符的字符串?

c++ - cmake:前导或尾随空格(策略 CMP0004)

c++ - 一个类在 C++ 中只包含(默认情况下)私有(private)成员有什么用处?

c++ - 为什么在 CToolBar 中使用高深度颜色的禁用按钮只是灰色框?

initialization - Modelica 中的稳态初始化

C++20 'familiar template' lambda : specifying an explicit argument in function pointer conversion

c++ - 当您可以从consteval函数创建constexpr对象时,为什么constexpr函数不能消耗consteval函数?