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)应对s1和s2,但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)
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)
| 归档时间: |
|
| 查看次数: |
1863 次 |
| 最近记录: |