我想知道,为什么std_arr在下面的代码中声明会产生错误,同时c_arr编译得很好:
struct S { int a, b; };
S c_arr[] = {{1, 2}, {3, 4}}; // OK
std::array<S, 2> std_arr = {{1, 2}, {3, 4}}; // Error: too many initializers
Run Code Online (Sandbox Code Playgroud)
双方std::array并S都聚集.从cppreference.com上的聚合初始化:
如果initializer子句是嵌套的braced-init-list(它不是表达式且没有类型),则相应的类成员本身就是一个聚合:聚合初始化是递归的.
为什么这个初始化std::array不能编译?
我的代码中有两种类型的结构变量初始化.
例
#include<iostream>
#include<string>
using namespace std;
struct Data{
int arr[5];
float x;
};
int main(){
struct Data d = {0};
struct Data d1 = {};
cout<<d.arr[0]<<d.x;
cout<<d1.arr[0]<<d1.x<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在运行代码广告获取0 0 0 0作为我的输出.请帮帮我,两者初始化有什么区别.
考虑以下代码:
#include <variant>
struct x {
int y;
};
int main() {
std::variant<x> v(std::in_place_type<x>, {3}); /*1*/
return std::get<x>(v).y;
}
Run Code Online (Sandbox Code Playgroud)
即使聚合初始化,这也不会编译,也不会{}从行中删除/*1*/
x a{3};
x b({3});
Run Code Online (Sandbox Code Playgroud)
适用于"类似构造函数"的形式.我可以以某种方式使std::variant初始化器知道使用聚合初始化构造结构的可能性,而不必为我的实际案例中可能使用的每个结构编写无聊的样板构造函数吗?
我希望这可以工作,不知何故,根据cppreference,有问题的两个重载(5)和(6)都说
使用指定的替代T构造变量并使用参数[...] 初始化包含的值
如果重要的话,我正在使用GCC 7.
如何就地构造一个可选的聚合?看来我只能构建一个可选的单一事物,而不能构建一个可选的事物集合。
#include <optional>
#include <iostream>
struct Unmovable
{
Unmovable(const Unmovable&) = delete;
Unmovable(Unmovable&&) = delete;
Unmovable& operator=(const Unmovable&) = delete;
Unmovable& operator=(Unmovable&&) = delete;
explicit Unmovable(const char* msg) {
std::cout << msg << '\n';
}
};
struct Things
{
Unmovable one;
Unmovable two;
};
int main(int argc, char* argv[]) {
const bool y = argc > 1 && argv[1][0] == 'y';
std::optional<Unmovable> optionalThing = y
? std::optional<Unmovable>{"works"}
: std::nullopt;
std::optional<Things> optionalThings = y
? std::optional<Things>{
#if ATTEMPT == 1
"jadda", …Run Code Online (Sandbox Code Playgroud) 请考虑这个简短的代码示例:
#include <iostream>
struct A
{
A() { std::cout << "A() "; }
~A() { std::cout << "~A() "; }
};
struct B { const A &a; };
struct C { const A &a = {}; };
int main()
{
B b({});
std::cout << ". ";
C c({});
std::cout << ". ";
}
Run Code Online (Sandbox Code Playgroud)
GCC 在这里打印(https://gcc.godbolt.org/z/czWrq8G5j)
A() ~A() . A() . ~A()
Run Code Online (Sandbox Code Playgroud)
这意味着A-object 初始化引用的生命周期b很短,但c生命周期会延长到作用域结束。
structsB和structs 之间的唯一区别在于C默认成员初始值设定项,它在 main() 中未使用 …
请考虑带有带有私有构造函数B的类字段的聚合结构的代码A:
class A { A(int){} friend struct B; };
struct B { A a{1}; };
int main()
{
B b; //ok everywhere, not aggregate initialization
//[[maybe_unused]] B x{1}; //error everywhere
[[maybe_unused]] B y{}; //ok in GCC and Clang, error in MSVC
}
Run Code Online (Sandbox Code Playgroud)
我的问题是关于B. 由于初始化是代表调用代码(main此处的函数)进行的,我预计编译器必须拒绝它,因为A的构造函数是私有的。事实上B{1},所有编译器的构造都失败了。
但令我惊讶的B{}是,GCC 和 Clang 都接受了该构造,演示:https : //gcc.godbolt.org/z/7851esv6Y
并且只有 MSVC 拒绝它并显示错误 error C2248: 'A::A': cannot access private member declared in class 'A'。 …
可以定义struct(a)没有用户定义的构造函数,(b)不能生成默认构造函数.例如,Foo在下面:
struct Baz
{
Baz(int) {}
};
struct Foo
{
int bar;
Baz baz;
};
Run Code Online (Sandbox Code Playgroud)
您仍然可以创建Foo使用聚合初始化的实例:
Foo foo = { 0, Baz(0) };
Run Code Online (Sandbox Code Playgroud)
我的普通编译器(VS2012)会勉强接受这个,但它会引发2个警告:
警告C4510:'Foo':无法生成默认构造函数.
警告C4610:struct'Foo'永远不能被实例化 - 需要用户定义的构造函数
当然,我刚刚证明警告#2错误 - 你仍然可以使用聚合初始化来实例化它.我尝试过的在线编译器很高兴接受上述内容,因此我猜测VS2012只是过于激进了这个警告.但我想确定 - 这段代码是否正常,还是技术上违反了标准中一些不起眼的部分?
c++ default-constructor language-lawyer aggregate-initialization visual-studio-2012
鉴于下面的示例,我很惊讶地发现尽管显式删除了默认构造函数(或者默认为此),但仍然可以进行聚合初始化.
#include <iostream>
struct DefaultPrivate
{
const int n_;
static const DefaultPrivate& create();
private:
DefaultPrivate() = delete;
};
const DefaultPrivate& DefaultPrivate::create()
{
static DefaultPrivate result{10};
return result;
}
int main() {
DefaultPrivate x; //Fails
DefaultPrivate y{10};//Works
return 0;
}
Run Code Online (Sandbox Code Playgroud)
私有默认(或删除)构造与聚合初始化之间的关系是否未在标准中指定?
GCC 6.3和VCC 2017就属于这种情况
我问这个问题的原因是,我希望更改对默认构造函数的访问会阻止公共聚合初始化
c++ initialization language-lawyer aggregate-initialization c++11
C++标准库必须std::is_constructible<Class, T...>检查是否可以从给定类型构造类作为参数.
例如,如果我有一个MyClass具有构造函数的类MyClass(int, char),那么std::is_constructible<MyClass, int, char>::value将是true.
是否有类似的标准库类型特征,将检查聚合初始化是否有效,即MyClass{int, char}格式良好并返回MyClass?
我的用例:
我想编写一个函数模板,std::tuple使用聚合初始化将其转换为(通常是POD)类,具有以下签名:
template <typename Class, typename... T>
inline Class to_struct(std::tuple<T...>&& tp);
Run Code Online (Sandbox Code Playgroud)
为了防止用户使用带有无效的函数Class,我可以static_assert在函数内部编写一个函数来检查给定tp参数是否具有可转换为成员的类型Class.这似乎是一种类型特征is_aggregate_initializable<Class, T...>会派上用场.
我可以推出自己的这个特性的实现,但仅仅是为了获取信息,标准库中有这样的特性我忽略了,还是很快就会成为标准库的一部分?
我基本上尝试编写自己的游戏引擎用于练习和个人使用(我知道,这是一项几乎不可能完成的任务,但正如我所说,它主要用于学习新事物).
目前,我正在研究我的数学库(主要是矢量和矩阵),我遇到了一个有趣的,但主要是美学问题.
template <uint8 size>
struct TVector {
float elements[size];
};
Run Code Online (Sandbox Code Playgroud)
现在我希望能够构造具有所需浮动量作为参数的结构:
TVector<3> vec0(1.0f, 2.5f, -4.0f);
TVector<2> vec1(3.0f, -2.0f);
TVector<3> vec2(2.0f, 2.2f); // Error: arg missing
TVector<2> vec3(1.0f, 2.0f, 3.0f) // Error: too many args
Run Code Online (Sandbox Code Playgroud)
由于数组的大小是由模板参数给出的,所以我很难为结构声明一个合适的构造函数.我的最终目标是这样的:
// This is pseudo-ideal-code
TVector(size * (float value)); // Create a constructor with number of size
// parameters, which are all floats
Run Code Online (Sandbox Code Playgroud)
当然,这是非逻辑语法,但我以这种方式最接近的是用C++ 17倍表达式:
template<typename... Args>
TVector(Args... values) {
static_assert(sizeof...(values) <= size, "Too many args");
uint8 i = 0;
(... , …Run Code Online (Sandbox Code Playgroud) c++ constructor aggregate-initialization variadic-templates fold-expression
c++ ×10
c++17 ×3
c++20 ×2
arrays ×1
c++11 ×1
c++14 ×1
construction ×1
constructor ×1
stdoptional ×1
struct ×1
type-traits ×1
variant ×1