我对以下编译器错误感到惊讶:
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
我经常在代码中遇到POD结构,这些结构是手动零初始化的,memset如下所示:
struct foo;
memset(&foo, 0, sizeof(foo));
Run Code Online (Sandbox Code Playgroud)
我检查了C++ 11标准,它说:"一个对象,其初始化器是一组空的括号,即(),应该进行值初始化." 接下来是: "对T类型的[pod结构]进行值初始化意味着...对象被零初始化."
所以......这是否意味着您可以随时安全地将上述代码压缩为以下代码:
struct foo{};
Run Code Online (Sandbox Code Playgroud)
并且有一个保证初始化的结构,就好像你已经调用了一样memset(&foo, 0, ...)?
如果是这样,那么一般来说,你可以使用空的初始化器安全地初始化任何东西,如下所示:
SomeUnknownType foo{}; // will 'foo' be completely "set" to known values?
Run Code Online (Sandbox Code Playgroud)
我知道在C++ 03中(在统一初始化语法之前)并不总是可行的,但现在C++ 11中是否可以用于任何类型?
在c ++ 11中,我们为对象提供了很好的统一初始化语法.为什么它不扩展到初始化非对象类型?
这有什么语法歧义,还是我问的一些愚蠢的问题?
例:
struct s{ int k;};
s s1{1}; //ok (object initialization)
s const& s3{3}; //ok (object initialization)
s& s2{s1}; //error (reference initialization)
Run Code Online (Sandbox Code Playgroud)
一个更有用的例子:
struct t{ t(t const& x) : k(x.k){} int k;};
struct c
{
c(t& x1,t& x2)
: s1_{x1} //error (reference initialization)
, s2_{x2} //ok (object initialization)
{}
t& s1_;
t s2_;
};
Run Code Online (Sandbox Code Playgroud)
另一个 :
template<class T>
T get()
{
return T{};
}
//ok (object initialization)
get<int>();
//error (void initialization? I do not know terminology for …Run Code Online (Sandbox Code Playgroud) 我鼓励这个问题:如果我有
class A
{
public:
};
int main()
{
A a{};
A b{a};
}
Run Code Online (Sandbox Code Playgroud)
gcc给出:
moves.cc:在函数'int main()'中:moves.cc:15:7:错误:'A'A b {a}的初始化程序太多;
但是当我使用A b(a)而不是A b {a}时,所有都能正确编译.如果我声明默认构造函数,它也会编译.为什么这样做?
在更新一些代码以使用统一初始化时,我认为它将成为现在"旧式"括号样式的现代替代品.我知道情况并非总是如此(显而易见的例子vector<int>),但我偶然发现了另一个我不理解的差异.
class Object {
public:
Object() = default;
Object(const Object&) = default;
};
int main() {
Object o;
Object copy{o}; // error
Object copy2(o); // OK
}
Run Code Online (Sandbox Code Playgroud)
无法在clang3.5下编译并出现错误:(在gcc下也失败)
error: excess elements in struct initializer
Run Code Online (Sandbox Code Playgroud)
这有两个不同的变化Object使这项工作.向其添加数据成员,或为其提供空复制构造函数体
class Object {
private:
int i; // this fixes it
public:
Object() = default;
Object(const Object&) { } // and/or this fixes it as well
};
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这些应该有所作为.
我熟悉使用花括号/初始化列表来防止在初始化变量时缩小,但是在为变量赋值时使用它是一种好习惯吗?
例如
int i{1}; // initialize i to 1
double d{2.0}; // initialize d to 2.0
i = {2}; // assign value 2 to i
i = {d}; // error: narrowing from double to int
Run Code Online (Sandbox Code Playgroud)
是否有理由不使用花括号进行分配?
我正在尝试使用C++字符串类的统一初始化程序.以下是代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 {"aaaaa"};
string str2 {5, 'a'};
string str3 (5, 'a');
cout << "str1: " << str1 << endl;
cout << "str2: " << str2 << endl;
cout << "str3: " << str3 << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出将是:
str1: aaaaa
str2: a
str3: aaaaa
Run Code Online (Sandbox Code Playgroud)
这让我摸不着头脑.为什么str2不能达到预期的效果str3呢?
假设我有一个FunctionWrapper像这样定义的类:
struct FunctionWrapper
{
FunctionWrapper(std::function<void()> f);
// ... plus other members irrelevant to the question
};
Run Code Online (Sandbox Code Playgroud)
我想,以防止隐式转换std::function<void()>到FunctionWrapper,但允许构建FunctionWrapper使用括号初始化语法(即使用初始化列表用一个参数).换句话说,我想这样:
void foo();
void wrap(FunctionWrapper);
wrap(foo); // (1) error
wrap({foo}); // (2) OK
wrap(FunctionWrapper{foo}); // (3) OK
Run Code Online (Sandbox Code Playgroud)
有没有办法实现这一目标?我上面定义类的方法不是它:这允许隐式转换,因此(1)编译.
如果我添加explicit到构造函数:
struct FunctionWrapper
{
explicit FunctionWrapper(std::function<void()> f);
// ... plus other members irrelevant to the question
};
Run Code Online (Sandbox Code Playgroud)
它也没有帮助,因为它"太过分"并且不允许(2)以及(1).
有没有办法实现"中间地带"并且(2)编译而(1)产生错误?
struct S
{
int x;
int y;
};
std::atomic<S> asd{{1, 2}}; // what should this be? This doesn't work
Run Code Online (Sandbox Code Playgroud)
编辑:这两个{{1, 2}}和({1, 2})在G ++,在铛没有工作的工作.clang有解决方法吗?
c++ atomic aggregate-initialization uniform-initialization c++11
作为一个更大项目的一部分,我正在玩std::tuple模板; 考虑以下代码:
template <typename ...T> void foo(tuple<T...> t) {}
void bar(tuple<int, char> t) {}
tuple<int, char> quxx() { return {1, 'S'}; }
int main(int argc, char const *argv[])
{
foo({1, 'S'}); // error
foo(make_tuple(1, 'S')); // ok
bar({1, 'S'}); // ok
quxx(); // ok
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据这个答案, C++ 17支持从复制列表初始化开始的元组初始化,但是由于我得到以下错误(GCC 7.2.0),所以似乎这种支持是有限的:
main.cpp: In function 'int main(int, const char**)':
main.cpp:14:17: error: could not convert '{1, 'S'}' from '<brace-enclosed initializer list>' to 'std::tuple<>'
foo({1, 'S'}); // error …Run Code Online (Sandbox Code Playgroud) c++ initializer-list variadic-templates uniform-initialization c++17