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

Ton*_*nyK 11 c++ stl initializer-list incomplete-type c++11

我有一个菜单系统,我想从常量数据初始化.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).难道我做错了什么?

Jam*_*lis 11

GMan的评论是正确的:S::v在你的代码声明中,S仍然是不完整的.必须完整的类型才能用作STL容器中的值类型.有关更多信息,请参阅Matt Austern的文章"标准图书馆员:不完整类型的容器".

如果您要切换到可用于不完整类型的容器,那么您的代码就可以了.例如,给出以下内容:

#include <initializer_list>

template <typename T>
struct Container
{
    Container() { }
    Container(std::initializer_list<T>) { }
};

struct S { Container<S> v; };
Run Code Online (Sandbox Code Playgroud)

那么你的原始初始化应该工作正常:

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

这也可以:

S s4 = { { { { { { { { { { { { { { { { /*zomg*/ } } } } } } } } } } } } } } } };
Run Code Online (Sandbox Code Playgroud)


Joh*_*itb 6

boost :: optional和boost :: recursive_wrapper看起来很有用

struct S { // one brace
    boost::optional< // another brace
      boost::recursive_wrapper< // another brace
        std::vector< // another brace
          S
        >
      >
    > v; 
};
Run Code Online (Sandbox Code Playgroud)

您添加的每个子菜单都需要4个大括号.涉及构造函数调用时,不会发生Brace elision.例如

S m{{{{ 
  {{{{ }}}}, 
  {{{{ 
    {{{{ }}}}, 
    {{{{ }}}} 
  }}}} 
}}}}; 
Run Code Online (Sandbox Code Playgroud)

老实说,使用构造函数看起来更具可读性

struct S {
    // this one is not really required by C++0x, but some GCC versions
    // require it.
    S(char const *s)
    :v(s) { } 

    S(std::string const& s)
    :v(s) { }

    S(std::initialize_list<S> s)
    :v(std::vector<S>(s)) { } 

    boost::variant<
      std::string,
      boost::recursive_wrapper<
        std::vector<
          S
        >
      >
    > v; 
};
Run Code Online (Sandbox Code Playgroud)

现在它简化为

S s{ 
  "S1", 
  {
    "SS1",
    "SS2",
    { "SSS1", "SSS2" }
  }
};
Run Code Online (Sandbox Code Playgroud)