Weird change in clang diagnostics with c++17 - c++

So in general this is more of a theoretical language lawyer question, than an actual one. While fighting with template with obscure template error, I found a behavior I could not explain with clang (bottom line - no warning that I am trying to move a class that is not movable). The weird thing is that the behaviour with clang changes depending on whether -std=c++17 is present or not.
So here is the MVP of the issue:
#include <utility>
struct INoLikeToMoveIt
{
INoLikeToMoveIt() = default;
INoLikeToMoveIt(const INoLikeToMoveIt&) = delete;
INoLikeToMoveIt(INoLikeToMoveIt&&) = delete;
INoLikeToMoveIt& operator=(const INoLikeToMoveIt&) = delete;
INoLikeToMoveIt& operator=(INoLikeToMoveIt&&) = delete;
};
int main()
{
INoLikeToMoveIt a, b;
auto c = std::make_pair(std::move(a), std::move(b));
return 0;
}
Obviously this will not work (but since in the actual case the non movable class was a member of a parent class hidden deep in the sources, w/o any warnings that it is not movable I could not immediately understand what is going on). So taking this example on godbolt with -std=c+=17 gives:
n file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/utility:70:
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:529:14: error: no matching constructor for initialization of '__pair_type' (aka 'pair<INoLikeToMoveIt, INoLikeToMoveIt>')
return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:15:19: note: in instantiation of function template specialization 'std::make_pair<INoLikeToMoveIt, INoLikeToMoveIt>' requested here
auto c = std::make_pair(std::move(a), std::move(b));
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:260:17: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_ConstructiblePair()' was not satisfied [with _U1 = INoLikeToMoveIt, _U2 = INoLikeToMoveIt]
constexpr pair(const _T1& __a, const _T2& __b)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:269:26: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_ConstructiblePair()' was not satisfied [with _U1 = INoLikeToMoveIt, _U2 = INoLikeToMoveIt]
explicit constexpr pair(const _T1& __a, const _T2& __b)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:311:18: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_MoveCopyPair()' was not satisfied [with _U1 = INoLikeToMoveIt]
constexpr pair(_U1&& __x, const _T2& __y)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:318:27: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_MoveCopyPair()' was not satisfied [with _U1 = INoLikeToMoveIt]
explicit constexpr pair(_U1&& __x, const _T2& __y)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:325:18: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_CopyMovePair()' was not satisfied [with _U2 = INoLikeToMoveIt]
constexpr pair(const _T1& __x, _U2&& __y)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:332:17: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_CopyMovePair()' was not satisfied [with _U2 = INoLikeToMoveIt]
explicit pair(const _T1& __x, _U2&& __y)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:341:12: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_MoveConstructiblePair()' was not satisfied [with _U1 = INoLikeToMoveIt, _U2 = INoLikeToMoveIt]
constexpr pair(_U1&& __x, _U2&& __y)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:350:21: note: candidate template ignored: requirement '_PCC<true, INoLikeToMoveIt, INoLikeToMoveIt>::_MoveConstructiblePair()' was not satisfied [with _U1 = INoLikeToMoveIt, _U2 = INoLikeToMoveIt]
explicit constexpr pair(_U1&& __x, _U2&& __y)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:229:26: note: candidate constructor template not viable: requires 0 arguments, but 2 were provided
_GLIBCXX_CONSTEXPR pair()
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:242:26: note: candidate constructor template not viable: requires 0 arguments, but 2 were provided
explicit constexpr pair()
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:291:19: note: candidate constructor template not viable: requires single argument '__p', but 2 arguments were provided
constexpr pair(const pair<_U1, _U2>& __p)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:300:21: note: candidate constructor template not viable: requires single argument '__p', but 2 arguments were provided
explicit constexpr pair(const pair<_U1, _U2>& __p)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:360:12: note: candidate constructor template not viable: requires single argument '__p', but 2 arguments were provided
constexpr pair(pair<_U1, _U2>&& __p)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:370:21: note: candidate constructor template not viable: requires single argument '__p', but 2 arguments were provided
explicit constexpr pair(pair<_U1, _U2>&& __p)
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:375:9: note: candidate constructor template not viable: requires 3 arguments, but 2 were provided
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:436:9: note: candidate constructor template not viable: requires 4 arguments, but 2 were provided
pair(tuple<_Args1...>&, tuple<_Args2...>&,
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:303:17: note: candidate constructor not viable: requires 1 argument, but 2 were provided
constexpr pair(const pair&) = default;
^
1 error generated.
Compiler returned: 1
which I would interpret as "hey I'm gonna tell you why you can't all the stuff you actually don't want, but not that the move ctor is deleted". Once I change -std=c++14 the same diagnostic but with a trailing lines:
<source>:15:10: error: call to implicitly-deleted copy constructor of 'std::pair<INoLikeToMoveIt, INoLikeToMoveIt>'
auto c = std::make_pair(std::move(a), std::move(b));
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:303:17: note: explicitly defaulted function was implicitly deleted here
constexpr pair(const pair&) = default;
^
/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:214:11: note: copy constructor of 'pair<INoLikeToMoveIt, INoLikeToMoveIt>' is implicitly deleted because field 'first' has a deleted copy constructor
_T1 first; /// #c first is a copy of the first object
^
<source>:6:5: note: 'INoLikeToMoveIt' has been explicitly marked deleted here
INoLikeToMoveIt(const INoLikeToMoveIt&) = delete;
^
2 errors generated.
Compiler returned: 1
which is still does not mention the deleted move c-tor, but at least points me to culprit. Initially I though, hey, maybe there is a new overload/semantics for std::make_pair that would cause this, but looking at std::make_pair does not show any C++17 relevant changes. So is this just a weird behaviour in diagnostics or is there an explanation for this? Just curios.

Related

Getting error while declaring size of 2D vector

I want to declare my 2D vector first, then give it a size.
But why I am getting error?
Can anyone explain me?
int main() {
vector<vector<int>> a;
a = vector<int>(16, vector<int>(15));
cout << a.size() << a[0].size();
}
The reason for doing it is that I don't know the size before but after getting the input from the user, I want to give it the size.
Error:
Char 9: error: no matching constructor for initialization of 'vector<int>'
a = vector<int>(16, vector<int>(15));
^ ~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:507:7: note: candidate constructor not viable: no known conversion from 'vector<int>' to 'const std::vector<int, std::allocator<int>>::allocator_type' (aka 'const std::allocator<int>') for 2nd argument
vector(size_type __n, const allocator_type& __a = allocator_type())
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:519:7: note: candidate constructor not viable: no known conversion from 'vector<int>' to 'const std::vector<int, std::allocator<int>>::value_type' (aka 'const int') for 2nd argument
vector(size_type __n, const value_type& __value,
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:572:7: note: candidate constructor not viable: no known conversion from 'int' to 'const std::vector<int, std::allocator<int>>' for 1st argument
vector(const vector& __x, const allocator_type& __a)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:604:7: note: candidate constructor not viable: no known conversion from 'int' to 'std::vector<int, std::allocator<int>>' for 1st argument
vector(vector&& __rv, const allocator_type& __m)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:622:7: note: candidate constructor not viable: no known conversion from 'int' to 'initializer_list<std::vector<int, std::allocator<int>>::value_type>' (aka 'initializer_list<int>') for 1st argument
vector(initializer_list<value_type> __l,
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:650:2: note: candidate template ignored: deduced conflicting types for parameter '_InputIterator' ('int' vs. 'std::vector<int, std::allocator<int>>')
vector(_InputIterator __first, _InputIterator __last,
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:494:7: note: candidate constructor not viable: requires single argument '__a', but 2 arguments were provided
vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:550:7: note: candidate constructor not viable: requires single argument '__x', but 2 arguments were provided
vector(const vector& __x)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:569:7: note: candidate constructor not viable: requires 1 argument, but 2 were provided
vector(vector&&) noexcept = default;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:582:7: note: candidate constructor not viable: requires 3 arguments, but 2 were provided
vector(vector&& __rv, const allocator_type& __m, true_type) noexcept
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:586:7: note: candidate constructor not viable: requires 3 arguments, but 2 were provided
vector(vector&& __rv, const allocator_type& __m, false_type)
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:484:7: note: candidate constructor not viable: requires 0 arguments, but 2 were provided
vector() = default;
^
1 error generated.
vector<int> is not a 2D vector.
Instead of this:
a = vector<int>(16, vector<int>(15));
You should use this:
a = vector<vector<int>>(16, vector<int>(15));

C++17 variant<any> inside the class

The following code compiles well:
int main()
{
variant<any> var;
var = 5;
cout << any_cast<int>(get<any>(var)) << endl;
return 0;
}
But when I'm trying to put variant<any> as a class member
struct MyClass{
variant<any> var;
};
int main()
{
MyClass s;
return 0;
}
It doesn't compile. Am I doing something wrong or it is some bug?
I'm using gcc 7.1.0
In file included from /home/zak/Projects/Anytest/main.cpp:3:0:
/usr/local/gcc-7.1/include/c++/7.1.0/variant: In instantiation of ‘struct std::__detail::__variant::__accepted_index<const std::variant<std::any>&, std::variant<std::any>, void>’:
/usr/local/gcc-7.1/include/c++/7.1.0/variant:911:26: required from ‘constexpr const size_t std::variant<std::any>::__accepted_index<const std::variant<std::any>&>’
/usr/local/gcc-7.1/include/c++/7.1.0/variant:940:6: required by substitution of ‘template<class _Tp, class> constexpr std::variant<std::any>::variant(_Tp&&) [with _Tp = const std::variant<std::any>&; <template-parameter-1-2> = <missing>]’
/home/zak/Projects/Anytest/main.cpp:14:13: required from here
/usr/local/gcc-7.1/include/c++/7.1.0/variant:559:49: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’
decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}]
static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}]
{ static void _S_fun(); };
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided
/usr/local/gcc-7.1/include/c++/7.1.0/variant:559:49: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’
decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}]
static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}]
{ static void _S_fun(); };
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided
/usr/local/gcc-7.1/include/c++/7.1.0/variant:559:49: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’
decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}]
static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}]
{ static void _S_fun(); };
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided
/usr/local/gcc-7.1/include/c++/7.1.0/variant: In instantiation of ‘constexpr const size_t std::__detail::__variant::__accepted_index<const std::variant<std::any>&, std::variant<std::any>, void>::value’:
/usr/local/gcc-7.1/include/c++/7.1.0/variant:911:26: required from ‘constexpr const size_t std::variant<std::any>::__accepted_index<const std::variant<std::any>&>’
/usr/local/gcc-7.1/include/c++/7.1.0/variant:940:6: required by substitution of ‘template<class _Tp, class> constexpr std::variant<std::any>::variant(_Tp&&) [with _Tp = const std::variant<std::any>&; <template-parameter-1-2> = <missing>]’
/home/zak/Projects/Anytest/main.cpp:14:13: required from here
/usr/local/gcc-7.1/include/c++/7.1.0/variant:564:12: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’
- decltype(__overload_set<_Types...>::
~~~~~~~~~~~~~~~~~~~~~~~~~~~
_S_fun(std::declval<_Tp>()))::value;
~~~~~~^~~~~~~~~~~~~~~~~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}]
static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First);
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}]
{ static void _S_fun(); };
^~~~~~
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided
The problem is with MyClass's implicitly defined copy constructor, when it tries to copy construct the member of type std::variant<std::any>.
To perform overload resolution, the compiler first needs to try to instantiate all of std::variant's constructor templates, with the function argument being a const std::variant<std::any>&1. The constructor of our interest is this one:
template <class T> constexpr variant(T&& t) noexcept(/*...*/);
It only participates in overload resolution if, among others, the expression FUN(​std​::​forward<T>(t)) is well formed, where FUN is a set of overloaded functions produced according to [variant.ctor]/12.2
In this case, there is only one alternative type (std::any), so there is only one imaginary function FUN, whose signature is FUN(std::any). Now, the compiler needs to decide whether FUN can be called with a const std::variant<std::any>&1. In this process, the compiler needs to know whether std::any can be constructed with const std::variant<std::any>&1.
This will trigger the instantiation of std::any's constructor template template<class T> any(T&& value);, which only participates in overload resolution if std::is_­copy_­constructible_­v<VT> is true (VT being std::decay_t<T>, and T being const std::variant<std::any>&).
Now in order to see whether VT (i.e. std::variant<std::any>) is copy constructible, the compiler needs to try to instantiate all of std::variant's constructor templates... and this is where we started, and we are stuck in a loop.
This can explain why we see template<class _Tp, class> constexpr std::variant<std::any>::variant(_Tp&&) and __overload_set<std::any>::_S_fun (which corresponds to the function FUN mentioned above) in the error message, and why we see the same error appearing several times.
It remains a question how GCC breaks from the above loop, and why tweaking the program can stop GCC from reporting the error. Maybe these are indication of some bug.
1. Strictly speaking, it should be "an lvalue of type const std::variant<std::any>" rather than "a const std::variant<std::any>&".
2. The standard also requires that this constructor shall only participate in overload resolution if is_­same_­v<decay_­t<T>, variant> is false. GCC (libstdc++) chooses to check that later. I don't know whether this is conforming.

unique_ptr and specifying deconstructors

When compiling my program with clang++ --std=c++11 file.cpp the line std::unique_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose); throws the error
memdiff.cpp:11:27: error: no matching constructor for initialization of
'std::unique_ptr<FILE>'
std::unique_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2530:31: note:
candidate constructor not viable: no known conversion from 'int (FILE *)'
to 'const std::__1::default_delete<__sFILE>' for 2nd argument
_LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, typename conditional<
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2537:31: note:
candidate constructor not viable: no known conversion from 'int (FILE *)'
to 'typename remove_reference<deleter_type>::type' (aka
'std::__1::default_delete<__sFILE>') for 2nd argument
_LIBCPP_INLINE_VISIBILITY unique_ptr(pointer __p, typename remove_ref...
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2547:9: note:
candidate template ignored: could not match 'unique_ptr<type-parameter-0-0,
type-parameter-0-1>' against '__sFILE *'
unique_ptr(unique_ptr<_Up, _Ep>&& __u,
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2562:35: note:
candidate template ignored: could not match 'auto_ptr<type-parameter-0-0>'
against '__sFILE *'
_LIBCPP_INLINE_VISIBILITY unique_ptr(auto_ptr<_Up>&& __p,
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2516:49: note:
candidate constructor not viable: requires 1 argument, but 2 were provided
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2522:40: note:
candidate constructor not viable: requires single argument '__p', but 2
arguments were provided
_LIBCPP_INLINE_VISIBILITY explicit unique_ptr(pointer __p) _NOEXCEPT
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2543:31: note:
candidate constructor not viable: requires single argument '__u', but 2
arguments were provided
_LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2487:29: note:
candidate constructor (the implicit copy constructor) not viable: requires
1 argument, but 2 were provided
class _LIBCPP_TYPE_VIS_ONLY unique_ptr
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:2510:49: note:
candidate constructor not viable: requires 0 arguments, but 2 were provided
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT
^
1 error generated.
If I switch from a unique_ptr to a shared_ptr my program compiles. Why does one constructor work and one not, and how do I fix it?
As correctly pointed out in the first comment: With unique_ptr, the type of the deleter must be specified as the second template parameter.
However, it's supposed to be a function pointer:
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);

Uniform Initialization with curly brace is mistaken as Initializer List

I have a class as:
#include <memory>
class Object {
std::shared_ptr<void> object_ptr;
public:
Object() {}
template<typename T>
Object(T&& object)
: object_ptr {new T {std::move(object)} } {}
virtual ~Object() {};
};
My main cpp file is:
#include <iostream>
#include "Object.hpp"
class Foo {};
int main() {
Object o {Foo{}};
}
It gives me error:
test/test.cpp:13:20: required from here
include/Object.hpp:24:49: error: could not convert ‘{std::move<Foo&>((* & object))}’ from ‘<brace-enclosed initializer list>’ to ‘Foo’
: object_ptr {new T {std::move(object)} } {}
^
include/Object.hpp:24:49: error: no matching function for call to ‘std::shared_ptr<void>::shared_ptr(<brace-enclosed initializer list>)’
include/Object.hpp:24:49: note: candidates are:
In file included from /usr/include/c++/4.8/memory:82:0,
from include/Object.hpp:7,
from test/test.cpp:2:
/usr/include/c++/4.8/bits/shared_ptr.h:314:2: note: template<class _Alloc, class ... _Args> std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...)
shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
^
/usr/include/c++/4.8/bits/shared_ptr.h:314:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:265:17: note: constexpr std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t) [with _Tp = void; std::nullptr_t = std::nullptr_t]
constexpr shared_ptr(nullptr_t __p) noexcept
^
/usr/include/c++/4.8/bits/shared_ptr.h:265:17: note: no known conversion for argument 1 from ‘<type error>’ to ‘std::nullptr_t’
/usr/include/c++/4.8/bits/shared_ptr.h:257:2: note: template<class _Tp1, class _Del> std::shared_ptr<_Tp>::shared_ptr(std::unique_ptr<_Up, _Ep>&&)
shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
^
/usr/include/c++/4.8/bits/shared_ptr.h:257:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:253:2: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Up>&&)
shared_ptr(std::auto_ptr<_Tp1>&& __r);
^
/usr/include/c++/4.8/bits/shared_ptr.h:253:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:248:11: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(const std::weak_ptr<_Tp1>&)
explicit shared_ptr(const weak_ptr<_Tp1>& __r)
^
/usr/include/c++/4.8/bits/shared_ptr.h:248:11: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:236:2: note: template<class _Tp1, class> std::shared_ptr<_Tp>::shared_ptr(std::shared_ptr<_Tp1>&&)
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
^
/usr/include/c++/4.8/bits/shared_ptr.h:236:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:226:7: note: std::shared_ptr<_Tp>::shared_ptr(std::shared_ptr<_Tp>&&) [with _Tp = void]
shared_ptr(shared_ptr&& __r) noexcept
^
/usr/include/c++/4.8/bits/shared_ptr.h:226:7: note: no known conversion for argument 1 from ‘<type error>’ to ‘std::shared_ptr<void>&&’
/usr/include/c++/4.8/bits/shared_ptr.h:218:2: note: template<class _Tp1, class> std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp1>&)
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
^
/usr/include/c++/4.8/bits/shared_ptr.h:218:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:206:2: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp1>&, _Tp*)
shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept
^
/usr/include/c++/4.8/bits/shared_ptr.h:206:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:184:2: note: template<class _Deleter, class _Alloc> std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t, _Deleter, _Alloc)
shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
^
/usr/include/c++/4.8/bits/shared_ptr.h:184:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:165:2: note: template<class _Tp1, class _Deleter, class _Alloc> std::shared_ptr<_Tp>::shared_ptr(_Tp1*, _Deleter, _Alloc)
shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
^
/usr/include/c++/4.8/bits/shared_ptr.h:165:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:146:2: note: template<class _Deleter> std::shared_ptr<_Tp>::shared_ptr(std::nullptr_t, _Deleter)
shared_ptr(nullptr_t __p, _Deleter __d)
^
/usr/include/c++/4.8/bits/shared_ptr.h:146:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:129:2: note: template<class _Tp1, class _Deleter> std::shared_ptr<_Tp>::shared_ptr(_Tp1*, _Deleter)
shared_ptr(_Tp1* __p, _Deleter __d)
^
/usr/include/c++/4.8/bits/shared_ptr.h:129:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:112:11: note: template<class _Tp1> std::shared_ptr<_Tp>::shared_ptr(_Tp1*)
explicit shared_ptr(_Tp1* __p)
^
/usr/include/c++/4.8/bits/shared_ptr.h:112:11: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/shared_ptr.h:103:7: note: std::shared_ptr<_Tp>::shared_ptr(const std::shared_ptr<_Tp>&) [with _Tp = void]
shared_ptr(const shared_ptr&) noexcept = default;
^
/usr/include/c++/4.8/bits/shared_ptr.h:103:7: note: no known conversion for argument 1 from ‘<type error>’ to ‘const std::shared_ptr<void>&’
/usr/include/c++/4.8/bits/shared_ptr.h:100:17: note: constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = void]
constexpr shared_ptr() noexcept
^
/usr/include/c++/4.8/bits/shared_ptr.h:100:17: note: candidate expects 0 arguments, 1 provided
make: *** [test.o] Error 1
However if I change new T {std::move(object)} to new T (std::move(object)). It works:
class Object {
std::shared_ptr<void> object_ptr;
public:
Object() {}
template<typename T>
Object(T&& object)
: object_ptr {new T (std::move(object)) } {}
virtual ~Object() {};
};
Why curly brace uniform initialization does not work here? Why is considered an initializater list in this case? Foo does not even have a constructor taking initializer list?
This was a known issue, and a defect in the standard (see CWG #1467). The proposal has been applied to the latest working paper (§8.5.4 [dcl.init.list]/3):
List-initialization of an object or reference of type T is defined as follows:
If T is a class type and the initializer list has a single element of type cv U, where U is T or a class derived
from T, the object is initialized from that element (by copy-initialization for copy-list-initialization, or
by direct-initialization for direct-list-initialization).
Note that trunk versions of Clang and GCC accept this code.

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.