Когда я пытаюсь запустить следующий код, и clang (6.0), и g ++ (8) с -std = c ++ 17 выдают ошибку static_assert:
#include <set>
struct A {};
struct ProcessComparator { inline bool operator()(const A&, const A&) { return true; } };
int main(void)
{
std::set<A, ProcessComparator> A_Set;
return EXIT_SUCCESS;
}
г ++ 8
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_tree.h:457:7: ошибка: Сбой static_assert из-за требования is_invocable_v «объект сравнения должен быть вызван как const»
лязг 6.0
/usr/include/c++/8/bits/stl_tree.h:457:21: ошибка: статическое утверждение не удалось: объект сравнения должен быть вызван как const
Помещение const в качестве части подписи operator () устраняет эту проблему:
#include <set>
struct A {};
/* Add const as part of the operator's signature */
struct ProcessComparator { inline bool operator()(const A&, const A&) const { return true; } };
int main(void)
{
std::set<A, ProcessComparator> A_Set;
return EXIT_SUCCESS;
}
Между тем при std = c ++ 14 ошибка исчезает как в clang, так и в g ++.
Мой вопрос: что изменилось в c ++ 17 для того, чтобы теперь выдавать ошибку, и почему здесь имеет значение const?
Const только гарантирует, что каждый объект, объявленный внутри класса ProcessComparator, не будет изменен (кроме объектов с изменяемым), так почему это требование?
Это исходный код из исходного кода, где статическое утверждение не выполняется:
#if __cplusplus >= 201103L
static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
"comparison object must be invocable with two arguments of key type");
# if __cplusplus >= 201703L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2542. Missing const requirements for associative containers
static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>,
"comparison object must be invocable as const");
# endif // C++17
#endif // C++11
Был добавлен новый static_assert, где объект сравнения был изменен с _Compare&<
в const _Compare&
а также is_invocable
в is_invocable_v
Хотя это, насколько я могу понять, это просто получить inline и constexpr как видно здесь
я обнаружил этот ссылка, основанная на комментарии исходного кода, но я до сих пор не могу понять Зачем это обязательно.
5
Решение
Задача ещё не решена.
Другие решения
Других решений пока нет …
The GCC 8 release series differs from previous GCC releases in
a number of ways. Some of these are a result
of bug fixing, and some old behaviors have been intentionally changed
to support new standards, or relaxed in standards-conforming ways to
facilitate compilation or run-time performance.
Some of these changes are user visible and can cause grief when
porting to GCC 8. This document is an effort to identify common issues
and provide solutions. Let us know if you have suggestions for improvements!
C++ language issues
-Wreturn-type
is enabled by default
G++ now assumes that control never reaches the end of a non-void function
(i.e. without reaching a return
statement). This means that
you should always pay attention to -Wreturn-type
warnings,
as they indicate code that can misbehave when optimized.
To tell the compiler that control can never reach the end of a function
(e.g. because all callers enforce its preconditions) you can suppress
-Wreturn-type
warnings by adding
__builtin_unreachable
:
char signchar(int i) // precondition: i != 0
{
if (i > 0)
return '+';
else if (i < 0)
return '-';
__builtin_unreachable();
}
Because -Wreturn-type
is now enabled by default, G++ will
warn if main
is declared with an implicit int
return type (which is non-standard but allowed by GCC). To avoid the
warning simply add a return type to main
, which makes the
code more portable anyway.
Stricter rules when using templates
G++ now diagnoses even more cases of ill-formed templates which can never
be instantiated (in addition to
the stricter
rules in GCC 7).
The following example will now be diagnosed by G++ because the type of
B<T>::a
does not depend on T
and so the
function B<T>::f
is ill-formed for every possible
instantiation of the template:
class A { };
template <typename T> struct B {
bool f() const { return a; }
A a;
};
In member function 'bool B<T>::f() const': error: cannot convert 'const A' to 'bool' in return bool f() const { return a; } ^
Ill-formed template code that has never been tested and can never be
instantiated should be fixed or removed.
Changes to alignof
results
The alignof
operator has been changed to return the minimum
alignment required by the target ABI, instead of the preferred alignment
(consistent with _Alignof
in C).
Previously the following assertions could fail on 32-bit x86 but will now
pass. GCC’s preferred alignment for standalone variables of type
double
or long long
is 8 bytes, but the minimum
alignment required by the ABI (and so used for non-static data members)
is 4 bytes:
struct D { double val; };
static_assert(alignof(D) == alignof(double), "...");
struct L { long long val; };
static_assert(alignof(L) == alignof(long long), "...");
Code which uses alignof
to obtain the preferred
alignment can use __alignof__
instead.
Associative containers check the comparison function
The associative containers (std::map
,
std::multimap
, std::set
, and
std::multiset
) now use static assertions to check that their
comparison functions support the necessary operations.
In C++17 mode this includes enforcing that the function can be called
when const
-qualified:
struct Cmp {
bool operator()(int l, int r) /* not const */ { return l < r; }
};
std::set<int, Cmp> s;
In member function 'bool B<T>::f() const': error: static assertion failed: comparison object must be invocable as const static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool f() const { return a; } ^
This can be fixed by adding const
to the call operator:
struct Cmp {
bool operator()(int l, int r) const { return l < r; }
};
Fortran language issues
The library ABI version has been increased, necessitating a
recompilation of all Fortran code.
Character lengths are now handled as
an INTEGER(kind=C_SIZE_T)
variable whose size is
dependent on the target system, allowing characters longer than
2**31 on 64-bit targets. Prior to GCC 8, the character length was
an INTEGER(kind=4)
variable on all targets. If calling
a Fortran procedure with character arguments from C (or vice versa)
without using the standard ISO_C_BINDING feature, the hidden
character length argument at the end of the argument list must thus
be modified to be of type size_t
rather than of
type int
. For instance, calling the Fortran subroutine
subroutine foo (s, a)
character(len=*) :: s
integer :: a
! Code here
end subroutine foo
from C in a way that is compatible with older GFortran versions can
be done by defining the prototype as follows:
#if __GNUC__ > 7
typedef size_t fortran_charlen_t;
#else
typedef int fortran_charlen_t;
#endif
void foo_ (char*, int*, fortran_charlen_t);
Versions of gfortran prior to 8.1 wrongly accepted CHARACTER
variables with a length type parameter other than one as C
interoperable. For example, the code
module mod
use iso_c_binding
type, bind(C) :: a
character(len=2,kind=c_char) :: b ! Wrong
end type a
character(len=2), bind(C) :: c ! Also wrong
end module mod
was accepted. To achieve similar functionality, an array of
LEN=1 characters can be used, for example
module mod
use iso_c_binding
type, bind(C) :: a
character(kind=c_char) :: b(2)
end type a
character(kind=c_char), bind(C) :: c(2)
end module mod
Open
Issue created Feb 27, 2022 by
Failure in GCC 11 STL when building CFS dependency for CC4S
Trying to build CC4S with GCC 11 apparently doesn’t work:
❯ mpicxx --showme
g++ -pthread -L/usr/lib/openmpi -Wl,-rpath -Wl,/usr/lib/openmpi -Wl,--enable-new-dtags -lmpi_cxx -lmpi
❯ mpicxx --showme:version
mpicxx: Open MPI 4.1.2 (Language: C++)
❯ mpicxx --version
g++ (GCC) 11.1.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
It fails when compiling CTF with
mpicxx -O3 -fopenmp -Wall -D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS -DFTN_UNDERSCORE=1 -DUSE_LAPACK -DUSE_SCALAPACK -c idx_tensor.cxx -o /home/awvwgk/projects/src/git/cc4s/extern/build/dist/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/obj/idx_tensor.o
In file included from /usr/include/c++/11.1.0/map:60,
from /usr/include/openmpi/ompi/mpi/cxx/mpicxx.h:42,
from /usr/include/mpi.h:2887,
from ../shared/model.h:7,
from common.h:18,
from idx_tensor.cxx:3:
/usr/include/c++/11.1.0/bits/stl_tree.h: In instantiation of ‘static const _Key& std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_S_key(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type) [with _Key = CTF::Idx_Tensor*; _Val = CTF::Idx_Tensor*; _KeyOfValue = std::_Identity<CTF::Idx_Tensor*>; _Compare = CTF_int::tensor_name_less; _Alloc = std::allocator<CTF::Idx_Tensor*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type = const std::_Rb_tree_node<CTF::Idx_Tensor*>*]’:
/usr/include/c++/11.1.0/bits/stl_tree.h:2069:47: required from ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = CTF::Idx_Tensor*; _Val = CTF::Idx_Tensor*; _KeyOfValue = std::_Identity<CTF::Idx_Tensor*>; _Compare = CTF_int::tensor_name_less; _Alloc = std::allocator<CTF::Idx_Tensor*>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = CTF::Idx_Tensor*]’
/usr/include/c++/11.1.0/bits/stl_tree.h:2122:4: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = CTF::Idx_Tensor*; _Key = CTF::Idx_Tensor*; _Val = CTF::Idx_Tensor*; _KeyOfValue = std::_Identity<CTF::Idx_Tensor*>; _Compare = CTF_int::tensor_name_less; _Alloc = std::allocator<CTF::Idx_Tensor*>]’
/usr/include/c++/11.1.0/bits/stl_set.h:521:25: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Tp>, _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 = CTF::Idx_Tensor*; _Compare = CTF_int::tensor_name_less; _Alloc = std::allocator<CTF::Idx_Tensor*>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Tp>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree<CTF::Idx_Tensor*, CTF::Idx_Tensor*, std::_Identity<CTF::Idx_Tensor*>, CTF_int::tensor_name_less, std::allocator<CTF::Idx_Tensor*> >::const_iterator; typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other = std::allocator<CTF::Idx_Tensor*>; typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key> = __gnu_cxx::__alloc_traits<std::allocator<CTF::Idx_Tensor*>, CTF::Idx_Tensor*>::rebind<CTF::Idx_Tensor*>; typename _Alloc::value_type = CTF::Idx_Tensor*; std::set<_Key, _Compare, _Alloc>::value_type = CTF::Idx_Tensor*]’
idx_tensor.cxx:346:23: required from here
/usr/include/c++/11.1.0/bits/stl_tree.h:770:15: error: static assertion failed: comparison object must be invocable as const
770 | is_invocable_v<const _Compare&, const _Key&, const _Key&>,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/11.1.0/bits/stl_tree.h:770:15: note: ‘std::is_invocable_v<const CTF_int::tensor_name_less&, CTF::Idx_Tensor* const&, CTF::Idx_Tensor* const&>’ evaluates to false
make[5]: *** [Makefile:12: /home/awvwgk/projects/src/git/cc4s/extern/build/dist/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/obj/idx_tensor.o] Error 1
make[5]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/src/interface'
make[4]: *** [Makefile:10: interface] Error 2
make[4]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/src'
make[3]: *** [Makefile:93: ctf_objs] Error 2
make[3]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776'
make[2]: *** [Makefile:238: /home/awvwgk/projects/src/git/cc4s/extern/build/dist/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/lib/libctf.a] Error 2
make[2]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776'
make[1]: *** [Makefile:4: all] Error 2
make[1]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/build/dist/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776'
make: *** [etc/make/ctf.mk:18: /home/awvwgk/projects/src/git/cc4s/extern/build/dist/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/lib/libctf.a] Error 2
Same for Intel 2021.0.5 (uses GCC 11 STL, so no big surprise)
❯ mpiicc -v
mpiicc for the Intel(R) MPI Library 2021.5 for Linux*
Copyright Intel Corporation.
icc version 2021.5.0 (gcc version 11.1.0 compatibility)
❯ mpiicc -show
icc -I"/opt/intel/oneapi/mpi/2021.5.1/include" -L"/opt/intel/oneapi/mpi/2021.5.1/lib/release" -L"/opt/intel/oneapi/mpi/2021.5.1/lib" -Xlinker --enable-new-dtags -Xlinker -rpath -Xlinker "/opt/intel/oneapi/mpi/2021.5.1/lib/release" -Xlinker -rpath -Xlinker "/opt/intel/oneapi/mpi/2021.5.1/lib" -lmpifort -lmpi -ldl -lrt -lpthread
Also fails in a static assert:
mpiicc -O3 -fopenmp -Wall -D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS -DFTN_UNDERSCORE=1 -DUSE_BATCH_GEMM -DUSE_LAPACK -DUSE_MKL -c world.cxx -o /home/awvwgk/projects/src/git/cc4s/extern/build/icc-mkl-impi/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/obj/world.o
mpiicc -O3 -fopenmp -Wall -D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS -DFTN_UNDERSCORE=1 -DUSE_BATCH_GEMM -DUSE_LAPACK -DUSE_MKL -c idx_tensor.cxx -o /home/awvwgk/projects/src/git/cc4s/extern/build/icc-mkl-impi/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/obj/idx_tensor.o
/usr/include/c++/11.1.0/bits/stl_tree.h(769): error: static assertion failed with "comparison object must be invocable as const"
static_assert(
^
detected during:
instantiation of "const _Key &std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_S_key(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Const_Link_type) [with _Key=CTF::Idx_Tensor *, _Val=CTF::Idx_Tensor *, _KeyOfValue=std::_Identity<CTF::Idx_Tensor *>, _Compare=CTF_int::tensor_name_less, _Alloc=std::allocator<CTF::Idx_Tensor *>]" at line 2069
instantiation of "std::pair<std::_Rb_tree_node_base *, std::_Rb_tree_node_base *> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type &) [with _Key=CTF::Idx_Tensor *, _Val=CTF::Idx_Tensor *, _KeyOfValue=std::_Identity<CTF::Idx_Tensor *>, _Compare=CTF_int::tensor_name_less, _Alloc=std::allocator<CTF::Idx_Tensor *>]" at line 2122
instantiation of "std::pair<std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg &&) [with _Key=CTF::Idx_Tensor *, _Val=CTF::Idx_Tensor *, _KeyOfValue=std::_Identity<CTF::Idx_Tensor *>, _Compare=CTF_int::tensor_name_less, _Alloc=std::allocator<CTF::Idx_Tensor *>, _Arg=CTF::Idx_Tensor *]" at line 521 of "/usr/include/c++/11.1.0/bits/stl_set.h"
instantiation of "std::pair<std::set<_Key, _Compare, _Alloc>::iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::value_type &&) [with _Key=CTF::Idx_Tensor *, _Compare=CTF_int::tensor_name_less, _Alloc=std::allocator<CTF::Idx_Tensor *>]" at line 346 of "idx_tensor.cxx"
compilation aborted for idx_tensor.cxx (code 2)
make[5]: *** [Makefile:12: /home/awvwgk/projects/src/git/cc4s/extern/build/icc-mkl-impi/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/obj/idx_tensor.o] Error 2
make[5]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/src/interface'
make[4]: *** [Makefile:10: interface] Error 2
make[4]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/src'
make[3]: *** [Makefile:93: ctf_objs] Error 2
make[3]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776'
make[2]: *** [Makefile:238: /home/awvwgk/projects/src/git/cc4s/extern/build/icc-mkl-impi/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/lib/libctf.a] Error 2
make[2]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/src/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776'
make[1]: *** [Makefile:4: all] Error 2
make[1]: Leaving directory '/home/awvwgk/projects/src/git/cc4s/extern/build/icc-mkl-impi/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776'
make: *** [etc/make/ctf.mk:18: /home/awvwgk/projects/src/git/cc4s/extern/build/icc-mkl-impi/ctf/f1d951de96c3f2fc5e76df2b0f6f6148e5216776/lib/libctf.a] Error 2
Bug 786495
— media-libs/exempi-2.4.5-r1 — /…/stl_tree.h: error: static assertion failed: comparison object must be invocable as const
Summary:
media-libs/exempi-2.4.5-r1 — /…/stl_tree.h: error: static assertion failed:…
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Note |