This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libstdc++/80654] is_trivially_copy_constructible fails with compiler error with vector of uncopyable objects
- From: "daniel.kruegler at googlemail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sat, 06 May 2017 20:12:45 +0000
- Subject: [Bug libstdc++/80654] is_trivially_copy_constructible fails with compiler error with vector of uncopyable objects
- Auto-submitted: auto-generated
- References: <bug-80654-4@http.gcc.gnu.org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654
Daniel Krügler <daniel.kruegler at googlemail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |daniel.kruegler@googlemail.
| |com
--- Comment #1 from Daniel Krügler <daniel.kruegler at googlemail dot com> ---
Here are two problems involved:
1) std::vector's copy constructor is not SFINAE-friendly and causes
std::is_copy_constructible to evaluate to true regradless of it's element type.
This is a QoI issue but not a violation of the requirements of the standard.
2) The more serious problem is that the intrinsic __is_trivially_constructible
is the actual cause of the non-silent response here. This can be demonstrated
by evaluating the statement
__is_trivially_constructible(std::vector<nocopy>, const std::vector<nocopy>&);
which results in the following compiler error:
//----------------------------
H:\Develop\Cpp\C++0x\ScratchBook\main.cpp||In function 'int main()':|
H:\Develop\Cpp\C++0x\ScratchBook\main.cpp|28|warning: statement has no effect
[-Wunused-value]|
c:\program files\develop\gcc\include\c++\8.0.0\bits\stl_construct.h||In
instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = nocopy;
_Args = {const nocopy&}]':|
c:\program
files\develop\gcc\include\c++\8.0.0\bits\stl_uninitialized.h|83|required from
'static _ForwardIterator
std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator,
_InputIterator, _ForwardIterator) [with _InputIterator =
__gnu_cxx::__normal_iterator<const nocopy*, std::vector<nocopy> >;
_ForwardIterator = nocopy*; bool _TrivialValueTypes = false]'|
c:\program
files\develop\gcc\include\c++\8.0.0\bits\stl_uninitialized.h|134|required from
'_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator,
_ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const
nocopy*, std::vector<nocopy> >; _ForwardIterator = nocopy*]'|
c:\program
files\develop\gcc\include\c++\8.0.0\bits\stl_uninitialized.h|289|required from
'_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator,
_ForwardIterator, std::allocator<_Tp>&) [with _InputIterator =
__gnu_cxx::__normal_iterator<const nocopy*, std::vector<nocopy> >;
_ForwardIterator = nocopy*; _Tp = nocopy]'|
c:\program files\develop\gcc\include\c++\8.0.0\bits\stl_vector.h|331|required
from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with
_Tp = nocopy; _Alloc = std::allocator<nocopy>]'|
H:\Develop\Cpp\C++0x\ScratchBook\main.cpp|28|required from here|
c:\program files\develop\gcc\include\c++\8.0.0\bits\stl_construct.h|75|error:
use of deleted function 'nocopy::nocopy(const nocopy&)'|
H:\Develop\Cpp\C++0x\ScratchBook\main.cpp|18|note: declared here|
||=== Build failed: 1 error(s), 7 warning(s) (0 minute(s), 0 second(s)) ===|
//----------------------------
Note that evaluating
std::is_copy_constructible<std::vector<nocopy>>
alone doesn't spit at the programmer, but happily instantiates.
The only clean choice is to fix the __is_trivially_constructible intrinsic.
Wrapping the current call of that intrinsic by expanding the current
std::is_trivially_copy_constructible definition as follows
template<typename _Tp>
struct __is_trivially_constructible_delayed
: public integral_constant<bool,
__is_trivially_constructible(_Tp, const _Tp&)>
{ };
template<typename _Tp>
struct is_trivially_copy_constructible
: public __and_<is_copy_constructible<_Tp>,
__is_trivially_constructible_delayed<_Tp>>
{ };
wouldn't solve the problem, because due to the wrong positive result of
std::is_copy_constructible<std::vector<nocopy>> the protected
__is_trivially_constructible_delayed would still be instantiated.