英文:
Aggregate initialization with nested map doesn't work expectedly
问题
It seems I was a bit fuzzy when posing this question since it have been a few days that I'm trying to fix this problem and couldn't reproduce it as an MRE probably the issue is somewhere else in my code. I am sorry for the time and effort of those who tried to answer this.
I want to store information about a graphql query so I need to store the selections for each field, this requires using a nested map. This is my how I tried to implement this however this won't compile for nested fields.
struct NestedContainer;
struct NestedContainer {
std::map<std::string, NestedContainer *> selections = std::map<std::string, NestedContainer *> ();
};
int main() {
auto a = NestedContainer({
{
{
"level1",
{
{
{
"level2",
{}
}
}
}
}
}
});
return 0;
}
clang output
<source>:15:13: error: no matching constructor for initialization of 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>')
{
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:204:7: note: candidate constructor not viable: cannot convert initializer list argument to 'const std::less<std::basic_string<char>>'
map(const _Compare& __comp,
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:217:7: note: candidate constructor not viable: cannot convert initializer list argument to 'const map<basic_string<char>, NestedContainer *>'
map(const map&) = default;
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:225:7: note: candidate constructor not viable: cannot convert initializer list argument to 'map<basic_string<char>, NestedContainer *>'
map(map&&) = default;
gcc
<source>: In function 'int main()':
<source>:25:5: error: could not convert '{{{"level1", {{{"level2", <brace-enclosed initializer list>()}}}}}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, NestedContainer*>'
25 | );
| ^
| |
| <brace-enclosed initializer list>
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:25:5: error: could not convert '{{{"level1", {{{"level2", <brace-enclosed initializer list>()}}}}}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, NestedContainer*>'
25 | );
| ^
| |
| <brace-enclosed initializer list>
Execution build compiler returned: 1
msvc
example.cpp
<source>(14): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'NestedContainer'
<source>(14): note: No constructor could take the source type, or constructor overload resolution was ambiguous
cl : Command line warning D9002 : ignoring unknown option '-std=c++20'
Compiler returned: 2
For those who ask why I use a pointer, not using a pointer fails as well.
struct NestedContainer {
std::map<std::string, NestedContainer> selections = std::map<std::string, NestedContainer *> ();
};
int main() {
auto a = NestedContainer({
{
{
"level1",
{
{
{
"level2",
{}
}
}
}
}
}
});
return 0;
}
msvc
<source>:8:55: error: no viable conversion from 'map[...], NestedContainer *>' to 'map[...], NestedContainer>'
std::map<std::string, NestedContainer> selections = std::map<std::string, NestedContainer *> ();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:217:7: note: candidate constructor not viable: no known conversion from 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>') to 'const map<basic_string<char>, NestedContainer> &' for 1st argument
map(const map&) = default;
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:225:7: note: candidate constructor not viable: no known conversion from 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>') to 'map<basic_string<char>, NestedContainer> &&' for 1st argument
map(map&&) = default;
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:238:7: note: candidate constructor not viable: no known conversion from 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>') to 'initializer_list<value_type>' (aka 'initializer_list<pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char>>, NestedContainer>>') for 1st argument
map(initializer_list<value_type> __l,
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:204:7: note: explicit constructor is not a candidate
map(const _Compare& __comp,
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:246:7: note: explicit constructor is not a candidate
map(const allocator_type& __a)
gcc
<source>:8:60: error: could not convert 'std::map<std::__cxx11::basic_string<char>, NestedContainer *>()' from 'map[...],NestedContainer *>' to 'map[...],NestedContainer>'
8 | std::map<std::string,
<details>
<summary>英文:</summary>
It seems I was a bit fuzzy when posing this question since it have been a few days that I'm trying to fix this problem and couldn't reproduce it as an MRE probably the issue is somewhere else in my code. I am sorry for the time and effort of those who tried to answer this.
___
I want to store information about a graphql query so I need to store
the selections for each field, this requires using a nested map.
This is my how I tried to implement this however this won't compile for nested
fields.
```cpp
struct NestedContainer;
struct NestedContainer {
std::map<std::string, NestedContainer *> selections = std::map<std::string, NestedContainer *> ();
};
int main() {
auto a = NestedContainer({
{
{
"level1",
{
{
{
"level2",
{}
}
}
}
}
}
});
return 0;
}
clang output
<source>:15:13: error: no matching constructor for initialization of 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>')
{
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:204:7: note: candidate constructor not viable: cannot convert initializer list argument to 'const std::less<std::basic_string<char>>'
map(const _Compare& __comp,
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:217:7: note: candidate constructor not viable: cannot convert initializer list argument to 'const map<basic_string<char>, NestedContainer *>'
map(const map&) = default;
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:225:7: note: candidate constructor not viable: cannot convert initializer list argument to 'map<basic_string<char>, NestedContainer *>'
map(map&&) = default;
gcc
<source>: In function 'int main()':
<source>:25:5: error: could not convert '{{{"level1", {{{"level2", <brace-enclosed initializer list>()}}}}}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, NestedContainer*>'
25 | );
| ^
| |
| <brace-enclosed initializer list>
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:25:5: error: could not convert '{{{"level1", {{{"level2", <brace-enclosed initializer list>()}}}}}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, NestedContainer*>'
25 | );
| ^
| |
| <brace-enclosed initializer list>
Execution build compiler returned: 1
msvc
example.cpp
<source>(14): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'NestedContainer'
<source>(14): note: No constructor could take the source type, or constructor overload resolution was ambiguous
cl : Command line warning D9002 : ignoring unknown option '-std=c++20'
Compiler returned: 2
For those who ask why I use a pointer, not using a pointer fails as well.
struct NestedContainer {
std::map<std::string, NestedContainer> selections = std::map<std::string, NestedContainer *> ();
};
int main() {
auto a = NestedContainer({
{
{
"level1",
{
{
{
"level2",
{}
}
}
}
}
}
});
return 0;
}
msvc
<source>:8:55: error: no viable conversion from 'map<[...], NestedContainer *>' to 'map<[...], NestedContainer>'
std::map<std::string, NestedContainer> selections = std::map<std::string, NestedContainer *> ();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:217:7: note: candidate constructor not viable: no known conversion from 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>') to 'const map<basic_string<char>, NestedContainer> &' for 1st argument
map(const map&) = default;
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:225:7: note: candidate constructor not viable: no known conversion from 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>') to 'map<basic_string<char>, NestedContainer> &&' for 1st argument
map(map&&) = default;
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:238:7: note: candidate constructor not viable: no known conversion from 'std::map<std::string, NestedContainer *>' (aka 'map<basic_string<char>, NestedContainer *>') to 'initializer_list<value_type>' (aka 'initializer_list<pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char>>, NestedContainer>>') for 1st argument
map(initializer_list<value_type> __l,
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:204:7: note: explicit constructor is not a candidate
map(const _Compare& __comp,
^
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/stl_map.h:246:7: note: explicit constructor is not a candidate
map(const allocator_type& __a)
gcc
<source>:8:60: error: could not convert 'std::map<std::__cxx11::basic_string<char>, NestedContainer*>()' from 'map<[...],NestedContainer*>' to 'map<[...],NestedContainer>'
8 | std::map<std::string, NestedContainer> selections = std::map<std::string, NestedContainer *> ();
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| map<[...],NestedContainer*>
<source>: In function 'int main()':
<source>:26:4: error: could not convert '{{{"level1", {{{"level2", <brace-enclosed initializer list>()}}}}}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, NestedContainer>'
26 | });
| ^
| |
| <brace-enclosed initializer list>
ASM generation compiler returned: 1
<source>:8:60: error: could not convert 'std::map<std::__cxx11::basic_string<char>, NestedContainer*>()' from 'map<[...],NestedContainer*>' to 'map<[...],NestedContainer>'
8 | std::map<std::string, NestedContainer> selections = std::map<std::string, NestedContainer *> ();
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| map<[...],NestedContainer*>
<source>: In function 'int main()':
<source>:26:4: error: could not convert '{{{"level1", {{{"level2", <brace-enclosed initializer list>()}}}}}}' from '<brace-enclosed initializer list>' to 'std::map<std::__cxx11::basic_string<char>, NestedContainer>'
26 | });
| ^
| |
| <brace-enclosed initializer list>
Execution build compiler returned: 1
msvc
example.cpp
/opt/compiler-explorer/windows/19.00.24210/include/xlocale(341): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
<source>(8): error C2664: 'std::map<std::string,NestedContainer,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>::map(const std::map<_Kty,_Ty,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>> &)': cannot convert argument 1 from 'std::map<std::string,NestedContainer *,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::initializer_list<std::pair<const _Kty,_Ty>>'
with
[
_Kty=std::string,
_Ty=NestedContainer
]
<source>(8): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
<source>(26): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'NestedContainer'
<source>(26): note: No constructor could take the source type, or constructor overload resolution was ambiguous
cl : Command line warning D9002 : ignoring unknown option '-std=c++20'
Compiler returned: 2
答案1
得分: 3
您的映射中的数值是NestedContainer *
(指针),而不是NestedContainer
。因此,您需要在大括号初始化器中获取指针。类似于:
auto a = NestedContainer{
{{"level1", new NestedContainer{
{{"level2", new NestedContainer}} }
}}
};
或者,从std::map
值类型中删除*
。
英文:
The values in your map are NestedContainer *
(pointers), not NestedContainer
. So you need to get pointers in the braced-initializer. Something like:
auto a = NestedContainer{
{{"level1", new NestedContainer{
{{"level2", new NestedContainer}} } }}
};
Alternately, remove the *
from the std::map value type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论