Unable to compile with unique_ptr and deleter - c++

I'm having trouble with unique_ptr and a deleter. The following won't compile:
unique_ptr<RSA> rsa(RSA_new(), ::RSA_free);
unique_ptr<RSA> rsa(RSA_new(), ptr_fun(RSA_free));
The compile errors are shown below.
shared_ptr worked fine, but I need to release one of those pointers when assigning it into another structure (and shared_ptr is not amicable).
I'm using GCC 4.7 on Debian 7.3 (x64). Everything is fully patched.
Any ideas what I am doing wrong?
../source/ac-pki.cpp:461:46: error: no matching function for call to ‘std::unique_ptr<rsa_st>::unique_ptr(RSA*, void (&)(RSA*))’
../source/ac-pki.cpp:461:46: note: candidates are:
In file included from /usr/include/c++/4.7/memory:86:0,
from /home/jwalton/test/include/ac-common.h:39,
from ../source/ac-pki.cpp:1:
/usr/include/c++/4.7/bits/unique_ptr.h:164:2: note: template<class _Up, class> std::unique_ptr::unique_ptr(std::auto_ptr<_Up>&&)
/usr/include/c++/4.7/bits/unique_ptr.h:164:2: note: template argument deduction/substitution failed:
../source/ac-pki.cpp:461:46: note: mismatched types ‘std::auto_ptr<_Up>’ and ‘RSA* {aka rsa_st*}’
In file included from /usr/include/c++/4.7/memory:86:0,
from /home/jwalton/test/include/ac-common.h:39,
from ../source/ac-pki.cpp:1:
/usr/include/c++/4.7/bits/unique_ptr.h:155:2: note: template<class _Up, class _Ep, class> std::unique_ptr::unique_ptr(std::unique_ptr<_Up, _Ep>&&)
/usr/include/c++/4.7/bits/unique_ptr.h:155:2: note: template argument deduction/substitution failed:
../source/ac-pki.cpp:461:46: note: mismatched types ‘std::unique_ptr<_Up, _Ep>’ and ‘RSA* {aka rsa_st*}’
In file included from /usr/include/c++/4.7/memory:86:0,
from /home/jwalton/test/include/ac-common.h:39,
from ../source/ac-pki.cpp:1:
/usr/include/c++/4.7/bits/unique_ptr.h:142:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<rsa_st>]
/usr/include/c++/4.7/bits/unique_ptr.h:142:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.7/bits/unique_ptr.h:136:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::nullptr_t = std::nullptr_t]
/usr/include/c++/4.7/bits/unique_ptr.h:136:17: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.7/bits/unique_ptr.h:130:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp>::pointer = rsa_st*; typename std::remove_reference<_To>::type = std::default_delete<rsa_st>]
/usr/include/c++/4.7/bits/unique_ptr.h:130:7: note: no known conversion for argument 2 from ‘void(RSA*) {aka void(rsa_st*)}’ to ‘std::remove_reference<std::default_delete<rsa_st> >::type&& {aka std::default_delete<rsa_st>&&}’
/usr/include/c++/4.7/bits/unique_ptr.h:125:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp>::pointer = rsa_st*; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<rsa_st>&]
/usr/include/c++/4.7/bits/unique_ptr.h:125:7: note: no known conversion for argument 2 from ‘void(RSA*) {aka void(rsa_st*)}’ to ‘std::conditional<false, std::default_delete<rsa_st>, const std::default_delete<rsa_st>&>::type {aka const std::default_delete<rsa_st>&}’
/usr/include/c++/4.7/bits/unique_ptr.h:120:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>; std::unique_ptr<_Tp, _Dp>::pointer = rsa_st*]
/usr/include/c++/4.7/bits/unique_ptr.h:120:7: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.7/bits/unique_ptr.h:114:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = rsa_st; _Dp = std::default_delete<rsa_st>]
/usr/include/c++/4.7/bits/unique_ptr.h:114:17: note: candidate expects 0 arguments, 2 provided
../source/ac-pki.cpp:550:91: error: cannot convert ‘std::unique_ptr<rsa_st>::pointer {aka rsa_st*}’ to ‘EVP_PKEY* {aka evp_pkey_st*}’ for argument ‘2’ to ‘int PEM_write_PKCS8PrivateKey(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, int (*)(char*, int, int, void*), void*)’
make: *** [source/ac-pki.o] Error 1

You need to give the type of the deleter as well
std::unique_ptr<RSA, void (*)(RSA*)> rsa(RSA_new(), ::RSA_free);
Otherwise, std::unique_ptr uses std::default_delete

The type of the deleter is part of the unique_ptr's type. So change your code to
std::unique_ptr<RSA, decltype(&::RSA_free)> p(RSA_new(), ::RSA_free);
Or, to cut down on the verbosity
using RSA_ptr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
RSA_ptr rsa(RSA_new(), ::RSA_free);

Related

Error using `make_shared<U[]>( std::size_t N )`

I am trying to implement a fixed size multi-dimensional array whose size is determined at runtime. with the (2) overload of make_shared (template<class T> shared_ptr<T> make_shared(std::size_t N) // T is U[]). However, I am facing compilation errors (logs below). The error is not present if I change the shareds to their unique counterparts. My question is,
What is this error about?
Why unique works?
Any better way to implement such runtime-fixed multi-dimentional array container?
Minimal working example:
#include <memory>
#include <iostream>
int main() {
typedef int cell_t;
std::size_t x, y;
std::cin >> y >> x;
auto layout = std::make_shared<std::shared_ptr<cell_t[]>[]>(y);
for (std::size_t i = 0; i < y; i += 1) {
layout[i] = std::make_shared<cell_t[]>(x);
}
return 0;
}
The error message from g++-10 is as follows (note suppressed for brevity)
In file included from /usr/include/c++/10/ext/alloc_traits.h:34,
from /usr/include/c++/10/bits/stl_uninitialized.h:67,
from /usr/include/c++/10/memory:66,
from test_shared.cpp:1:
/usr/include/c++/10/bits/alloc_traits.h: In instantiation of ‘static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::shared_ptr<int []>; _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []> []; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<std::shared_ptr<int []> []>]’:
/usr/include/c++/10/bits/shared_ptr_base.h:551:39: required from ‘std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...) [with _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []>; _Alloc = std::allocator<std::shared_ptr<int []> []>; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10/bits/shared_ptr_base.h:682:16: required from ‘std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = std::shared_ptr<int []>; _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10/bits/shared_ptr_base.h:1371:71: required from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []> []; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10/bits/shared_ptr.h:408:59: required from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []> []]’
/usr/include/c++/10/bits/shared_ptr.h:859:14: required from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = std::shared_ptr<int []> []; _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}]’
/usr/include/c++/10/bits/shared_ptr.h:875:39: required from ‘std::shared_ptr<_Tp> std::make_shared(_Args&& ...) [with _Tp = std::shared_ptr<int []> []; _Args = {long unsigned int&}]’
test_shared.cpp:7:63: required from here
/usr/include/c++/10/bits/alloc_traits.h:514:21: error: no matching function for call to ‘construct_at(std::shared_ptr<int []>*&, long unsigned int&)’
514 | std::construct_at(__p, std::forward<_Args>(__args)...);
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/10/memory:65,
from test_shared.cpp:1:
/usr/include/c++/10/bits/stl_construct.h: In substitution of ‘template<class _Tp, class ... _Args> constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = std::shared_ptr<int []>; _Args = {long unsigned int&}]’:
/usr/include/c++/10/bits/alloc_traits.h:514:21: required from ‘static constexpr void std::allocator_traits<std::allocator<_Up> >::construct(std::allocator_traits<std::allocator<_Up> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::shared_ptr<int []>; _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []> []; std::allocator_traits<std::allocator<_Up> >::allocator_type = std::allocator<std::shared_ptr<int []> []>]’
/usr/include/c++/10/bits/shared_ptr_base.h:551:39: required from ‘std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...) [with _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []>; _Alloc = std::allocator<std::shared_ptr<int []> []>; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10/bits/shared_ptr_base.h:682:16: required from ‘std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = std::shared_ptr<int []>; _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10/bits/shared_ptr_base.h:1371:71: required from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []> []; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10/bits/shared_ptr.h:408:59: required from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}; _Tp = std::shared_ptr<int []> []]’
/usr/include/c++/10/bits/shared_ptr.h:859:14: required from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = std::shared_ptr<int []> []; _Alloc = std::allocator<std::shared_ptr<int []> []>; _Args = {long unsigned int&}]’
/usr/include/c++/10/bits/shared_ptr.h:875:39: required from ‘std::shared_ptr<_Tp> std::make_shared(_Args&& ...) [with _Tp = std::shared_ptr<int []> []; _Args = {long unsigned int&}]’
test_shared.cpp:7:63: required from here
/usr/include/c++/10/bits/stl_construct.h:96:17: error: no matching function for call to ‘std::shared_ptr<int []>::shared_ptr(long unsigned int&)’
96 | -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
g++-10 -v output:
Using built-in specs.
COLLECT_GCC=g++-10
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 10.2.0-5ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-10-WJNXnb/gcc-10-10.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-10-WJNXnb/gcc-10-10.2.0/debian/tmp-gcn/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04)
And from clang:
In file included from test_shared.cpp:1:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/memory:64:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/allocator.h:46:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10/bits/c++allocator.h:33:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:150:23: error: no matching constructor for initialization of 'std::shared_ptr<int []>'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:512:8: note: in instantiation of function template specialization '__gnu_cxx::new_allocator<std::shared_ptr<int []> []>::construct<std::shared_ptr<int []>, unsigned long &>' requested here
__a.construct(__p, std::forward<_Args>(__args)...);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:551:30: note: in instantiation of function template specialization 'std::allocator_traits<std::allocator<std::shared_ptr<int []> []> >::construct<std::shared_ptr<int []>, unsigned long &>' requested here
allocator_traits<_Alloc>::construct(__a, _M_ptr(),
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:683:6: note: in instantiation of function template specialization 'std::_Sp_counted_ptr_inplace<std::shared_ptr<int []>, std::allocator<std::shared_ptr<int []> []>, __gnu_cxx::_S_atomic>::_Sp_counted_ptr_inplace<unsigned long &>' requested here
_Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr_base.h:1371:14: note: in instantiation of function template specialization 'std::__shared_count<__gnu_cxx::_S_atomic>::__shared_count<std::shared_ptr<int []>, std::allocator<std::shared_ptr<int []> []>, unsigned long &>' requested here
: _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:408:4: note: in instantiation of function template specialization 'std::__shared_ptr<std::shared_ptr<int []> [], __gnu_cxx::_S_atomic>::__shared_ptr<std::allocator<std::shared_ptr<int []> []>, unsigned long &>' requested here
: __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:859:14: note: in instantiation of function template specialization 'std::shared_ptr<std::shared_ptr<int []> []>::shared_ptr<std::allocator<std::shared_ptr<int []> []>, unsigned long &>' requested here
return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:875:19: note: in instantiation of function template specialization 'std::allocate_shared<std::shared_ptr<int []> [], std::allocator<std::shared_ptr<int []> []>, unsigned long &>' requested here
return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
^
test_shared.cpp:7:21: note: in instantiation of function template specialization 'std::make_shared<std::shared_ptr<int []> [], unsigned long &>' requested here
auto layout = std::make_shared<std::shared_ptr<cell_t[]>[]>(y);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:149:7: note: candidate constructor not viable: no known conversion from 'unsigned long' to 'const std::shared_ptr<int []>' for 1st argument
shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:303:7: note: candidate constructor not viable: no known conversion from 'unsigned long' to 'std::shared_ptr<int []>' for 1st argument
shared_ptr(shared_ptr&& __r) noexcept
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:356:17: note: candidate constructor not viable: no known conversion from 'unsigned long' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:159:2: note: candidate template ignored: could not match '_Yp *' against 'unsigned long'
shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:295:2: note: candidate template ignored: could not match 'shared_ptr<type-parameter-0-0>' against 'unsigned long'
shared_ptr(const shared_ptr<_Yp>& __r) noexcept
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:312:2: note: candidate template ignored: could not match 'shared_ptr<type-parameter-0-0>' against 'unsigned long'
shared_ptr(shared_ptr<_Yp>&& __r) noexcept
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:324:11: note: candidate template ignored: could not match 'weak_ptr<type-parameter-0-0>' against 'unsigned long'
explicit shared_ptr(const weak_ptr<_Yp>& __r)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:331:2: note: candidate template ignored: could not match 'auto_ptr<type-parameter-0-0>' against 'unsigned long'
shared_ptr(auto_ptr<_Yp>&& __r);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:339:2: note: candidate template ignored: could not match 'unique_ptr<type-parameter-0-0, type-parameter-0-1>' against 'unsigned long'
shared_ptr(unique_ptr<_Yp, _Del>&& __r)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:348:2: note: candidate template ignored: could not match 'unique_ptr<type-parameter-0-0, type-parameter-0-1>' against 'unsigned long'
shared_ptr(unique_ptr<_Yp, _Del>&& __r)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:407:2: note: candidate template ignored: could not match '_Sp_alloc_shared_tag<type-parameter-0-0>' against 'unsigned long'
shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:147:17: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:176:2: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
shared_ptr(_Yp* __p, _Deleter __d)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:193:2: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
shared_ptr(nullptr_t __p, _Deleter __d)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:256:2: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:416:7: note: candidate constructor not viable: requires 2 arguments, but 1 was provided
shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:213:2: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/shared_ptr.h:232:2: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
^
1 error generated.
clang -v output:
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Candidate multilib: .;#m64
Selected multilib: .;#m64
Original code, if it helps,
class gridmap {
private:
std::shared_ptr<std::shared_ptr<cell_t[]>[]> layout;
std::size_t w;
std::size_t h;
public:
gridmap(std::size_t y, std::size_t x) {
layout = std::make_shared<std::shared_ptr<cell_t[]>[]>(y);
for (std::size_t i = 0; i < y; i += 1) {
layout[i] = std::make_shared<cell_t[]>(x);
}
h = y;
w = x;
}
std::shared_ptr<cell_t[]>& operator[](size_t r) {
return layout[r];
}
};
For your first question "What is this error about?":
GCC libstdc++ and Clang libc++ has no support for "Extending std::make_shared() to support arrays " which introduced in c++20 yet. So these compilers will try to use template< class T, class... Args > shared_ptr<T> make_shared( Args&&... args );, which trying to forward your arguments (in this case, a cell_t = std::size_t) to construct a std::shared_ptr<cell_t[]>[]. It cannot be done, so they complain about it.
You can check compiler compatibility here: Compiler support for C++20

C++ Initializing a unique_ptr array attribute in a class

I wish to use a unique_ptr for my class here (instead of vector for my own reasons). But I'm not sure how to initialize a new [] array with it. Here is what my code looks like
template <typename T>
class kmap
{
private:
const std::vector<std::string> &data;
std::unique_ptr<T> table;
public:
kmap(std::vector<std::string> &kmers);
};
template <typename T>
kmap<T>::kmap(std::vector<std::string> &kmers) : data(kmers)
{
this->table = std::unique_ptr<T[]>(new T[kmers.size()*2]);
}
Now I can initialize this with std::unique_ptr<T>(new T[kmers.size()*2] ); but I am skeptical that it may only delete the very first element of the array instead of freeing the entire block when the object goes out of scope. Is my skepticism in vain or is it possible to initialize this as an array?
Here is a part of the error message of what I get when initializing this with T =int:
/home/sflash/Documents/misc/kmap.cpp: In instantiation of ‘kmap<T>::kmap(std::vector<std::__cxx11::basic_string<char> >&) [with T = int]’:
/home/sflash/Documents/misc/kmap.cpp:75:23: required from here
/home/sflash/Documents/misc/kmap.cpp:27:15: error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<int, std::default_delete<int> >’ and ‘std::unique_ptr<int [], std::default_delete<int []> >’)
27 | this->table = std::unique_ptr<T[]>(new T[kmers.size()*2]);
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/10.2.0/memory:83,
from /home/sflash/Documents/misc/kmap.cpp:2:
/usr/include/c++/10.2.0/bits/unique_ptr.h:371:19: note: candidate: ‘std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = std::default_delete<int>]’
371 | unique_ptr& operator=(unique_ptr&&) = default;
| ^~~~~~~~
/usr/include/c++/10.2.0/bits/unique_ptr.h:371:29: note: no known conversion for argument 1 from ‘std::unique_ptr<int [], std::default_delete<int []> >’ to ‘std::unique_ptr<int, std::default_delete<int> >&&’
371 | unique_ptr& operator=(unique_ptr&&) = default;
| ^~~~~~~~~~~~
/usr/include/c++/10.2.0/bits/unique_ptr.h:386:2: note: candidate: ‘template<class _Up, class _Ep> typename std::enable_if<std::__and_<std::__and_<std::is_convertible<typename std::unique_ptr<_Up, _Ep>::pointer, typename std::__uniq_ptr_impl<_Tp, _Dp>::pointer>, std::__not_<std::is_array<_Up> > >, std::is_assignable<_T2&, _U2&&> >::value, std::unique_ptr<_Tp, _Dp>&>::type std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Up, _Ep>&&) [with _Up = _Up; _Ep = _Ep; _Tp = int; _Dp = std::default_delete<int>]’
386 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
How I compiled: g++ -pipe -O2 -std=c++14 "$file" -o exe -lm
unique_ptr has a specialization when declared with an array type:
std::unique_ptr<T[]> table;
In this situation, delete[] will be used to delete the pointer.
As a bonus, this specialization also defines an overloaded operator[] to make it easier to use as an array.

Correct syntax to assign unique_ptr to new boost::asio::io_service::work object?

What's the correct syntax to assign a std::unique_ptr<boost::asio::io_service::work> pointer to a new boost::asio::io_service::work object?
I am converting boost::asio code from using static functions and global variables to a class implementation, but this means I have to replace the working initialization:
std::unique_ptr<boost::asio::io_service::work> KeepAlive(
new boost::asio::io_service::work(TheASIOService));
with a class member variable in a class definition:
std::unique_ptr<boost::asio::io_service::work> KeepAlive;
later assigned to a new value:
KeepAlive = new boost::asio::io_service::work(IO_Service);
Which the compiler rejects based on the parameter type (brace for Boost error):
g++ -std=c++0x -c -Wall ../comms/CommServer.cpp
../comms/CommServer.cpp: In member function ‘void CommServer::Listen()’:
../comms/CommServer.cpp:39:13: error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<boost::asio::io_service::work>’ and ‘boost::asio::io_service::work*’)
KeepAlive = new boost::asio::io_service::work(IO_Service);
^
../comms/CommServer.cpp:39:13: note: candidates are:
In file included from /usr/include/c++/4.8/memory:81:0,
from /usr/include/boost/config/no_tr1/memory.hpp:21,
from /usr/include/boost/get_pointer.hpp:14,
from /usr/include/boost/bind/mem_fn.hpp:25,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../comms/Comms.h:16,
from ../comms/CommServer.h:16,
from ../comms/CommServer.cpp:10:
/usr/include/c++/4.8/bits/unique_ptr.h:190:7: note: std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = boost::asio::io_service::work; _Dp = std::default_delete<boost::asio::io_service::work>]
operator=(unique_ptr&& __u) noexcept
^
/usr/include/c++/4.8/bits/unique_ptr.h:190:7: note: no known conversion for argument 1 from ‘boost::asio::io_service::work*’ to ‘std::unique_ptr<boost::asio::io_service::work>&&’
/usr/include/c++/4.8/bits/unique_ptr.h:203:2: note: template<class _Up, class _Ep> typename std::enable_if<std::__and_<std::is_convertible<typename std::unique_ptr<_Up, _Ep>::pointer, typename std::unique_ptr<_Tp, _Dp>::_Pointer::type>, std::__not_<std::is_array<_Up> > >::value, std::unique_ptr<_Tp, _Dp>&>::type std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Up, _Ep>&&) [with _Up = _Up; _Ep = _Ep; _Tp = boost::asio::io_service::work; _Dp = std::default_delete<boost::asio::io_service::work>]
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
^
/usr/include/c++/4.8/bits/unique_ptr.h:203:2: note: template argument deduction/substitution failed:
../comms/CommServer.cpp:39:13: note: mismatched types ‘std::unique_ptr<_Tp, _Dp>’ and ‘boost::asio::io_service::work*’
KeepAlive = new boost::asio::io_service::work(IO_Service);
^
In file included from /usr/include/c++/4.8/memory:81:0,
from /usr/include/boost/config/no_tr1/memory.hpp:21,
from /usr/include/boost/get_pointer.hpp:14,
from /usr/include/boost/bind/mem_fn.hpp:25,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../comms/Comms.h:16,
from ../comms/CommServer.h:16,
from ../comms/CommServer.cpp:10:
/usr/include/c++/4.8/bits/unique_ptr.h:211:7: note: std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::nullptr_t) [with _Tp = boost::asio::io_service::work; _Dp = std::default_delete<boost::asio::io_service::work>; std::nullptr_t = std::nullptr_t]
operator=(nullptr_t) noexcept
^
/usr/include/c++/4.8/bits/unique_ptr.h:211:7: note: no known conversion for argument 1 from ‘boost::asio::io_service::work*’ to ‘std::nullptr_t’
I checked the documentation for the unique_ptr's assignment operator and see that the example for some reason wraps an assigned value in a call to std::move(), but the compiler balks at that in a similar way:
g++ -std=c++0x -c -Wall ../comms/CommServer.cpp
../comms/CommServer.cpp: In member function ‘void CommServer::Listen()’:
../comms/CommServer.cpp:39:13: error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<boost::asio::io_service::work>’ and ‘std::remove_reference<boost::asio::io_service::work*>::type {aka boost::asio::io_service::work*}’)
KeepAlive = std::move(new boost::asio::io_service::work(IO_Service));
^
../comms/CommServer.cpp:39:13: note: candidates are:
In file included from /usr/include/c++/4.8/memory:81:0,
from /usr/include/boost/config/no_tr1/memory.hpp:21,
from /usr/include/boost/get_pointer.hpp:14,
from /usr/include/boost/bind/mem_fn.hpp:25,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../comms/Comms.h:16,
from ../comms/CommServer.h:16,
from ../comms/CommServer.cpp:10:
/usr/include/c++/4.8/bits/unique_ptr.h:190:7: note: std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = boost::asio::io_service::work; _Dp = std::default_delete<boost::asio::io_service::work>]
operator=(unique_ptr&& __u) noexcept
^
/usr/include/c++/4.8/bits/unique_ptr.h:190:7: note: no known conversion for argument 1 from ‘std::remove_reference<boost::asio::io_service::work*>::type {aka boost::asio::io_service::work*}’ to ‘std::unique_ptr<boost::asio::io_service::work>&&’
/usr/include/c++/4.8/bits/unique_ptr.h:203:2: note: template<class _Up, class _Ep> typename std::enable_if<std::__and_<std::is_convertible<typename std::unique_ptr<_Up, _Ep>::pointer, typename std::unique_ptr<_Tp, _Dp>::_Pointer::type>, std::__not_<std::is_array<_Up> > >::value, std::unique_ptr<_Tp, _Dp>&>::type std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Up, _Ep>&&) [with _Up = _Up; _Ep = _Ep; _Tp = boost::asio::io_service::work; _Dp = std::default_delete<boost::asio::io_service::work>]
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
^
/usr/include/c++/4.8/bits/unique_ptr.h:203:2: note: template argument deduction/substitution failed:
../comms/CommServer.cpp:39:13: note: mismatched types ‘std::unique_ptr<_Tp, _Dp>’ and ‘std::remove_reference<boost::asio::io_service::work*>::type {aka boost::asio::io_service::work*}’
KeepAlive = std::move(new boost::asio::io_service::work(IO_Service));
^
In file included from /usr/include/c++/4.8/memory:81:0,
from /usr/include/boost/config/no_tr1/memory.hpp:21,
from /usr/include/boost/get_pointer.hpp:14,
from /usr/include/boost/bind/mem_fn.hpp:25,
from /usr/include/boost/mem_fn.hpp:22,
from /usr/include/boost/bind/bind.hpp:26,
from /usr/include/boost/bind.hpp:22,
from ../comms/Comms.h:16,
from ../comms/CommServer.h:16,
from ../comms/CommServer.cpp:10:
/usr/include/c++/4.8/bits/unique_ptr.h:211:7: note: std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::nullptr_t) [with _Tp = boost::asio::io_service::work; _Dp = std::default_delete<boost::asio::io_service::work>; std::nullptr_t = std::nullptr_t]
operator=(nullptr_t) noexcept
^
/usr/include/c++/4.8/bits/unique_ptr.h:211:7: note: no known conversion for argument 1 from ‘std::remove_reference<boost::asio::io_service::work*>::type {aka boost::asio::io_service::work*}’ to ‘std::nullptr_t’
Reading the docs on std::move, I see that there are some new pointer concepts I don't quite grok, and should read up on, but until then, I'd rather like a working ::work object.
Is this unique_ptr protecting me from doing something that would invalidate its guarantees? Should I not be using unique_ptr here? Or do I just not have the right syntax? Should I be using unique_ptr::reset(new ...)?
Use unique_ptr::reset:
keepAlive.reset(new boost::asio::io_service::work(IO_Service));
It's valid to use a unique_ptr for deferred construction, although it would be more ideal to use std/boost optional unless you also explicitly need/want to dynamically allocate it. I'll also note that you should attempt to design your classes so that you can fully construct everything in the constructor and not need deferred construction. But sometimes it's unavoidable.
Check out the documentation for std::unique_ptr<>. You'll find that unique_ptr<>::reset() is your friend:
KeepAlive.reset(new boost::asio::io_service::work(IO_Service));

Templated move ctor for wrapped unique_ptr

I want something that's like unique_ptr, but guaranteed (within reason) to be non-null. I wrote this class that contains a unique_ptr, and I wrote this move constructor that I'd hoped would allow me to move-construct one of my pointers from another, as long as the underlying unique_ptr could be similarly move-constructed. So, I first try it with something simple; move-constructing a pointer-to-int from a pointer-to-int.
#include <memory>
#include <utility>
#include <cassert>
template<
typename T
>
class Nonup
{
private:
std::unique_ptr<T> m_ptr;
public:
explicit Nonup( T* p )
: m_ptr( p )
{ assert( p ); }
Nonup( const Nonup& ) = delete;
Nonup& operator=( const Nonup& ) = delete;
template<typename U>
Nonup( Nonup<U>&& old )
:
m_ptr( std::move( old ) )
{}
Nonup& operator=( Nonup&& rhs ) = default;
decltype( *m_ptr ) operator*() const { return *m_ptr; }
};
int main()
{
Nonup<int> first( new int( 42 ) );
Nonup<int> second( std::move( first ) );
return 0;
}
Why does g++ 4.7.0 give errors on the move-construction of the variable second? The output of "g++ -std=c++11 main.cpp" follows.
main.cpp: In instantiation of ‘Nonup<T>::Nonup(Nonup<U>&&) [with U = int; T = int]’:
main.cpp:40:43: required from here
main.cpp:27:37: error: no matching function for call to ‘std::unique_ptr<int, std::default_delete<int> >::unique_ptr(std::remove_reference<Nonup<int>&>::type)’
main.cpp:27:37: note: candidates are:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template<class _Up, class> std::unique_ptr::unique_ptr(std::auto_ptr<_Up>&&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template argument deduction/substitution failed:
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::auto_ptr<_Up>’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template<class _Up, class _Ep, class> std::unique_ptr::unique_ptr(std::unique_ptr<_Up, _Ep>&&)
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template argument deduction/substitution failed:
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::unique_ptr<_Up, _Ep>’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0,
from main.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >&&’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = int; _Dp = std::default_delete<int>; std::nullptr_t = std::nullptr_t]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::nullptr_t’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::remove_reference<_To>::type = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: candidate expects 2 arguments, 1 provided
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<int>&]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: candidate expects 2 arguments, 1 provided
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >::pointer {aka int*}’
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = std::default_delete<int>]
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: candidate expects 0 arguments, 1 provided
Thanks!
You're trying to initialise m_ptr from the other Nonup, rather than its m_ptr. The move constructor's initialiser should be:
m_ptr( std::move( old.m_ptr ) )
^^^^^^

gcc 4.7 STL library deficit on pair implementation?

The following code compiles on gcc 4.6 but not 4.7. Is it 4.7's problem or 4.6's problem? Compiled with -std=gnu++0x.
#include <utility>
using namespace std;
struct Z {
};
struct X {
operator Z*() const { return nullptr; }
};
struct Y {
Y(Z*) {}
};
int main() {
pair<int, Y> p(make_pair(0, X()));
}
Error messages:
[hidden]$ g++-mp-4.6 -std=gnu++0x e.cpp
[hidden]$ g++-mp-4.7 -std=gnu++0x e.cpp
e.cpp: In function 'int main()':
e.cpp:17:37: error: no matching function for call to 'std::pair<int, Y>::pair(std::pair<int, X>)'
e.cpp:17:37: note: candidates are:
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:204:9: note: template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)
/opt/local/include/gcc47/c++/bits/stl_pair.h:204:9: note: template argument deduction/substitution failed:
e.cpp:17:37: note: 'std::pair<int, X>' is not derived from 'std::tuple<_Args1 ...>'
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:153:9: note: template<class ... _Args1, class ... _Args2> std::pair::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)
/opt/local/include/gcc47/c++/bits/stl_pair.h:153:9: note: template argument deduction/substitution failed:
e.cpp:17:37: note: cannot convert 'std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = X; typename std::__decay_and_strip<_T2>::__type = X; typename std::__decay_and_strip<_T1>::__type = int]((* & X()))' (type 'std::pair<int, X>') to type 'std::piecewise_construct_t'
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:148:12: note: template<class _U1, class _U2, class> constexpr std::pair::pair(std::pair<_U1, _U2>&&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:148:12: note: template argument deduction/substitution failed:
/opt/local/include/gcc47/c++/bits/stl_pair.h:145:38: error: no type named 'type' in 'struct std::enable_if<false, void>'
/opt/local/include/gcc47/c++/bits/stl_pair.h:142:12: note: template<class _U1, class _U2, class> constexpr std::pair::pair(_U1&&, _U2&&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:142:12: note: template argument deduction/substitution failed:
e.cpp:17:37: note: candidate expects 2 arguments, 1 provided
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:136:12: note: template<class _U2, class> constexpr std::pair::pair(const _T1&, _U2&&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:136:12: note: template argument deduction/substitution failed:
e.cpp:17:37: note: cannot convert 'std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = X; typename std::__decay_and_strip<_T2>::__type = X; typename std::__decay_and_strip<_T1>::__type = int]((* & X()))' (type 'std::pair<int, X>') to type 'const int&'
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:131:12: note: template<class _U1, class> constexpr std::pair::pair(_U1&&, const _T2&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:131:12: note: template argument deduction/substitution failed:
e.cpp:17:37: note: candidate expects 2 arguments, 1 provided
In file included from /opt/local/include/gcc47/c++/utility:72:0,
from e.cpp:1:
/opt/local/include/gcc47/c++/bits/stl_pair.h:122:7: note: std::pair<_T1, _T2>::pair(std::pair<_T1, _T2>&&) [with _T1 = int; _T2 = Y; std::pair<_T1, _T2> = std::pair<int, Y>]
/opt/local/include/gcc47/c++/bits/stl_pair.h:122:7: note: no known conversion for argument 1 from 'std::pair<int, X>' to 'std::pair<int, Y>&&'
/opt/local/include/gcc47/c++/bits/stl_pair.h:119:17: note: constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = Y; std::pair<_T1, _T2> = std::pair<int, Y>]
/opt/local/include/gcc47/c++/bits/stl_pair.h:119:17: note: no known conversion for argument 1 from 'std::pair<int, X>' to 'const std::pair<int, Y>&'
/opt/local/include/gcc47/c++/bits/stl_pair.h:116:12: note: template<class _U1, class _U2, class> constexpr std::pair::pair(const std::pair<_U1, _U2>&)
/opt/local/include/gcc47/c++/bits/stl_pair.h:116:12: note: template argument deduction/substitution failed:
/opt/local/include/gcc47/c++/bits/stl_pair.h:113:38: error: no type named 'type' in 'struct std::enable_if<false, void>'
/opt/local/include/gcc47/c++/bits/stl_pair.h:104:26: note: constexpr std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = int; _T2 = Y]
/opt/local/include/gcc47/c++/bits/stl_pair.h:104:26: note: candidate expects 2 arguments, 1 provided
/opt/local/include/gcc47/c++/bits/stl_pair.h:100:26: note: constexpr std::pair<_T1, _T2>::pair() [with _T1 = int; _T2 = Y]
/opt/local/include/gcc47/c++/bits/stl_pair.h:100:26: note: candidate expects 0 arguments, 1 provided
That shouldn't compile.
The initialisation of p.second requires an implicit conversion from X to Y. An implicit conversion can only involve at most one user-defined conversion The required conversion would require two; X to Z* via the conversion operator, and Z* to Y via the conversion constructor.
Initialisation of pair elements from another pair is only allowed via implicit conversions. C++11 says:
20.3.2/12 This constructor shall not participate in overload resolution unless const U& is implicitly convertible to first_type and const V& is implicitly convertible to second_type.
and C++98 said:
20.2.2/4 Initializes members from the corresponding members of the argument, performing implicit conversions as needed.
Presumably, the older version had a bug which allowed this conversion to be considered, and that bug has been fixed in the more recent version.