我有一个菜单系统,我想从常量数据初始化.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).难道我做错了什么?
以下代码无法在GCC 4.7.2或Clang 3.2中编译:
#include <vector>
#include <functional>
int main()
{
std::vector<std::function<void()>> a;
std::vector<std::function<void()>> b{a};
}
Run Code Online (Sandbox Code Playgroud)
问题是编译器将尝试使用initializer_list创建b,显然它应该只是调用复制构造函数.然而,这似乎是期望的行为,因为标准表明initializer_list构造函数应该优先.
这段代码适用于其他std :: vector,但对于std :: function,编译器无法知道你是否需要initializer_list构造函数或其他构造函数.
它似乎没有办法解决它,如果是这种情况,那么你永远不能在模板化代码中使用统一初始化.这将是一个巨大的耻辱.
另一方面,Visual Studio(2012年11月CTP)并没有抱怨这一点.但是此时initializer_list支持不是很好,所以它可能是一个bug.
编辑:在我们开始之前,这个问题不是关于正确使用std::initializer_list; 它是关于在需要方便的语法时应该传递什么.谢谢你坚持主题.
C++ 11引入std::initializer_list了定义接受braced-init-list参数的函数.
struct bar {
bar( char const * );
bar( int );
} dog( 42 );
fn foo( std::initializer_list< bar > args );
foo( { "blah", 3, dog } );
Run Code Online (Sandbox Code Playgroud)
语法很好,但由于各种问题,它很糟糕:
他们无法有意义地感动.上述功能必须dog从列表中复制; 这不能转换为移动建筑或省略.仅移动类型根本无法使用.(好吧,const_cast实际上是一个有效的解决方法.如果有一篇关于这样做的文章,我希望看到它.)
也没有constexpr语义.(这在C++ 1y即将发布.但这是一个小问题.)
const不像其他地方那样传播; 的initializer_list是从来没有const,但它的内容始终是.(因为它不拥有其内容,所以它不能对副本进行写访问,尽管将它复制到任何地方都很少是安全的.)
该initializer_list对象不拥有其存储(yikes); 它与提供存储的完全独立的裸阵列(yikes)的关系被隐含地定义(yikes)作为引用与绑定临时(四倍yikes)的关系.
我相信这些事情会在适当的时候得到解决,但是现在是否有最佳实践来获得没有硬编码的优势initializer_list?是否有关于直接依赖它的文献或分析?
显而易见的解决方案是通过值传递标准容器,例如std::vector.一旦将对象从中复制到其中initializer_list,它就会被移动构造为按值传递,然后您可以移出内容.改进是在堆栈上提供存储.一个好的图书馆也许能提供大部分的优点initializer_list,array和vector,甚至不需要使用前者.
有资源吗?
C++中的初始化列表构造函数经常会引起麻烦; 例如
using std::vector;
using std::string;
vector<string> v{3}; // vector of three empty strings
vector<int> u{3}; // vector of one element with value 3
Run Code Online (Sandbox Code Playgroud)
(只是为了澄清,我的意思是<int>构造函数是一个初始化列表构造函数,而<string>一个不是.)
该int案例与初始化列表构造函数匹配,而string案例则不匹配.这有点难看,常常会造成麻烦.在Scott Meyers的Effective Modern C++的早期章节(第7项)中也注意到了这一点,他将其描述为标准中有些令人不快的部分,每当初始化列表构造函数可用时,编译器将跳过箍尝试匹配它,优先于每个其他构造函数.
当然,int case可以通过改变u{3}来轻松修复u(3),但这不是重点.
这是理想的行为吗?C++标准委员会是否有任何讨论或计划来解决这种模糊/不愉快?一个例子是要求初始化程序列表构造函数被调用,如下所示:vector<int> u({3})这已经是合法的.
假设我有:
// MyClass.h
class MyClass
{
public:
MyClass();
private:
Something *something_;
}
// MyClass.cpp
MyClass::MyClass()
{
something_ = new Something();
}
Run Code Online (Sandbox Code Playgroud)
我应该在MyClass构造函数的构造函数初始化列表中初始化something_到NULL(或0)吗?或者这是不必要的,因为我在构造函数的主体中分配它?建议的做法是什么?
我对以下编译器错误感到惊讶:
template <typename T>
struct A
{
A(T t): t_{t} {}
T t_;
};
struct S
{
};
int main()
{
A<S> s{S{}};
}
Run Code Online (Sandbox Code Playgroud)
错误是(与clang):
test.cpp:4:16: error: excess elements in struct initializer
A(T t): t_{t} {}
^
test.cpp:15:10: note: in instantiation of member function 'A<S>::A' requested here
A<S> s{S{}};
^
Run Code Online (Sandbox Code Playgroud)
GCC给出了类似的错误.
我希望表达t_{t},试图复制构建t_从t.由于S有一个隐式生成的复制构造函数,我不希望这是一个问题.
有人能解释一下这里发生了什么吗?
c++ copy-constructor initializer-list uniform-initialization c++11
假设有一个接受多个字符串的函数:
void fun (const std::initializer_list<std::string>& strings) {
for(auto s : strings)
// do something
}
Run Code Online (Sandbox Code Playgroud)
现在,我有一个可变template函数说foo():
template<typename ...Args>
void foo () {
fun(???);
}
Run Code Online (Sandbox Code Playgroud)
此方法在外部称为:
foo<A, B, C, D>(); // where A, B, C, D are classes
Run Code Online (Sandbox Code Playgroud)
这些作为参数传递的类应该包含一个公共static const成员:
static const std::string value = "...";
Run Code Online (Sandbox Code Playgroud)
以下是我的问题(如何):
foo(),检查是否所有Args包含value使用
static_assertfun()给形成initializer_list; 例如
fun({A::value, B::value, ...});搜索了几个与可变参数模板及其解包相关的线程,但我仍然是这个领域的新手.非常感谢更详细的解释.
我有一个简单的函数,它应该构造一些对象并返回它们的向量,同时还转移所有权.我认为这样做的最好方法就是返回一个std::vector<std::unique_ptr<int>>对象(让我们说它们就是这样int).
当我尝试以下功能时:
std::vector<std::unique_ptr<int>> create_stuff() {
auto first = std::make_unique<int>(1);
auto second = std::make_unique<int>(2);
return {std::move(first), std::move(second)};
}
Run Code Online (Sandbox Code Playgroud)
我受到了很长的编译错误的欢迎,结果是:
xmemory0(737): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)':
attempting to reference a deleted function
Run Code Online (Sandbox Code Playgroud)
我认为问题在于函数本身,但是以下解决方案工作正常:
std::vector<std::unique_ptr<int>> create_stuff() {
auto first = std::make_unique<int>(1);
auto second = std::make_unique<int>(2);
std::vector<std::unique_ptr<int>> results;
results.push_back(std::move(first));
results.push_back(std::move(second));
return results;
}
Run Code Online (Sandbox Code Playgroud)
为什么第二种解决方案有效但不是第一种?有没有一种解决方法可以让我在初始化列表中使用简短的语法?
我有一个关于 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> …
我正在尝试使用它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++ ×10
initializer-list ×10
c++11 ×6
constructor ×2
compiler-bug ×1
pointers ×1
stl ×1
templates ×1
unique-ptr ×1