std::set<int * const> 无法编译
std::set<int * const> won't compile
这里的const
是编译问题的原因。然而,自己实现了一个AVL树,我不明白为什么。
代码如下:
#include <set>
int main ()
{
int a;
// I want the set to carry the "promise"
// to keep the pointers constant
std::set<int * const> x;
x.insert(&a);
}
这是错误:
In file included from /usr/include/c++/7/string:48:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from demo.cpp:1:
/usr/include/c++/7/bits/stl_function.h: In instantiation of ‘struct std::_Identity<int* const>’:
/usr/include/c++/7/bits/stl_tree.h:2091:29: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = int* const; _Key = int* const; _Val = int* const; _KeyOfValue = std::_Identity<int* const>; _Compare = std::less<int* const>; _Alloc = std::allocator<int* const>]’
/usr/include/c++/7/bits/stl_set.h:510:48: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::value_type&&) [with _Key = int* const; _Compare = std::less<int* const>; _Alloc = std::allocator<int* const>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<int* const>; std::set<_Key, _Compare, _Alloc>::value_type = int* const]’
demo.cpp:11:18: required from here
/usr/include/c++/7/bits/stl_function.h:877:7: error: ‘const _Tp& std::_Identity<_Tp>::operator()(const _Tp&) const [with _Tp = int* const]’ cannot be overloaded
operator()(const _Tp& __x) const
^~~~~~~~
/usr/include/c++/7/bits/stl_function.h:873:7: error: with ‘_Tp& std::_Identity<_Tp>::operator()(_Tp&) const [with _Tp = int* const]’
operator()(_Tp& __x) const
有没有“干净”的方法来做到这一点? (即,不是像在这种情况下使用比较器制作“指针 class”这样的变通方法)
这里有一个简单的程序来演示您遇到的问题:
int main(int argc, char ** argv)
{
int * const a = NULL;
int * const b = NULL;
b = a; // error: cannot assign to variable 'b' with const-qualified type
}
请注意,更改 int * const
变量的值是一个编译时错误,因为该变量被认为是只读的。
std::set
内部也有同样的问题--需要修改指定类型的变量,如果指定类型为只读则不能修改
将类型更改为 const int *
可能是您想要做的,因为该类型允许在必要时覆盖指针(同时不允许修改它们指向的 int
到).
您不能修改存储在 std::set
中的元素,因此这一点没有实际意义。它旨在使元素保持有序,修改会破坏该保证。这就是迭代器(std::set<T>::iterator
和 std::set<T>::const_iterator
)both return const references 的原因。
无法编辑缺少 mutable
(或 const_cast
)的元素,在这种情况下您仍然需要保证顺序保持不变。
更正式的回答是 std::set meets the requirements of being AllocatorAwareContainer:
A set satisfies all of the requirements of a container, of a
reversible container ([container.requirements]), of an associative
container ([associative.reqmts]), and of an allocator-aware container
(Table 65).
在 [allocator.requirements] 中 table 33 你可以阅读:
T, U, C any cv-unqualified object type ([basic.types])
其中 T 与 X::value_type 相同,其中 X 为 an allocator class for type T
。这意味着 std::allocator<int * const>
不符合上述要求。
许多其他容器也是如此,例如 vector,您可以在此处阅读更多内容:Does C++11 allow vector<const T>?
[编辑[
Visual Studio 给出了稍微更多的描述性错误:
C:\Program Files (x86)\Microsoft Visual Studio
14.0\VC\INCLUDE\xmemory0(585): error C2338: The C++ Standard forbids containers of const elements because allocator is ill-formed.
使用 clang,您可能会看到第一个错误行指向分配器 headers:
../include/c++/5.5.0/ext/new_allocator.h:93:7: 错误:'address' 的多个重载实例化为相同的签名 '__gnu_cxx::new_allocator::const_pointer (__gnu_cxx::new_allocator::const_reference) const noexcept' (aka 'int *const *(int *const &) const noexcept')
地址(const_reference __x).......
这里的const
是编译问题的原因。然而,自己实现了一个AVL树,我不明白为什么。
代码如下:
#include <set>
int main ()
{
int a;
// I want the set to carry the "promise"
// to keep the pointers constant
std::set<int * const> x;
x.insert(&a);
}
这是错误:
In file included from /usr/include/c++/7/string:48:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from demo.cpp:1:
/usr/include/c++/7/bits/stl_function.h: In instantiation of ‘struct std::_Identity<int* const>’:
/usr/include/c++/7/bits/stl_tree.h:2091:29: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = int* const; _Key = int* const; _Val = int* const; _KeyOfValue = std::_Identity<int* const>; _Compare = std::less<int* const>; _Alloc = std::allocator<int* const>]’
/usr/include/c++/7/bits/stl_set.h:510:48: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::value_type&&) [with _Key = int* const; _Compare = std::less<int* const>; _Alloc = std::allocator<int* const>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<int* const>; std::set<_Key, _Compare, _Alloc>::value_type = int* const]’
demo.cpp:11:18: required from here
/usr/include/c++/7/bits/stl_function.h:877:7: error: ‘const _Tp& std::_Identity<_Tp>::operator()(const _Tp&) const [with _Tp = int* const]’ cannot be overloaded
operator()(const _Tp& __x) const
^~~~~~~~
/usr/include/c++/7/bits/stl_function.h:873:7: error: with ‘_Tp& std::_Identity<_Tp>::operator()(_Tp&) const [with _Tp = int* const]’
operator()(_Tp& __x) const
有没有“干净”的方法来做到这一点? (即,不是像在这种情况下使用比较器制作“指针 class”这样的变通方法)
这里有一个简单的程序来演示您遇到的问题:
int main(int argc, char ** argv)
{
int * const a = NULL;
int * const b = NULL;
b = a; // error: cannot assign to variable 'b' with const-qualified type
}
请注意,更改 int * const
变量的值是一个编译时错误,因为该变量被认为是只读的。
std::set
内部也有同样的问题--需要修改指定类型的变量,如果指定类型为只读则不能修改
将类型更改为 const int *
可能是您想要做的,因为该类型允许在必要时覆盖指针(同时不允许修改它们指向的 int
到).
您不能修改存储在 std::set
中的元素,因此这一点没有实际意义。它旨在使元素保持有序,修改会破坏该保证。这就是迭代器(std::set<T>::iterator
和 std::set<T>::const_iterator
)both return const references 的原因。
无法编辑缺少 mutable
(或 const_cast
)的元素,在这种情况下您仍然需要保证顺序保持不变。
更正式的回答是 std::set meets the requirements of being AllocatorAwareContainer:
A set satisfies all of the requirements of a container, of a reversible container ([container.requirements]), of an associative container ([associative.reqmts]), and of an allocator-aware container (Table 65).
在 [allocator.requirements] 中 table 33 你可以阅读:
T, U, C any cv-unqualified object type ([basic.types])
其中 T 与 X::value_type 相同,其中 X 为 an allocator class for type T
。这意味着 std::allocator<int * const>
不符合上述要求。
许多其他容器也是如此,例如 vector,您可以在此处阅读更多内容:Does C++11 allow vector<const T>?
[编辑[
Visual Studio 给出了稍微更多的描述性错误:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(585): error C2338: The C++ Standard forbids containers of const elements because allocator is ill-formed.
使用 clang,您可能会看到第一个错误行指向分配器 headers:
../include/c++/5.5.0/ext/new_allocator.h:93:7: 错误:'address' 的多个重载实例化为相同的签名 '__gnu_cxx::new_allocator::const_pointer (__gnu_cxx::new_allocator::const_reference) const noexcept' (aka 'int *const *(int *const &) const noexcept') 地址(const_reference __x).......