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.
Related
This question already has answers here:
How to enable_shared_from_this of both parent and derived
(6 answers)
Closed 2 years ago.
Can't std::shared_from_this be inherited by its derived classes?
Why doesn't this code snippet compile(check http://cpp.sh/7llcr)? I have read the documentation(https://en.cppreference.com/w/cpp/memory/enable_shared_from_this) carefully, but still can't find any clue. I have thought about it for a long. I would be very grateful to have some help with this question.
Here is the code snippet which does not compile:
// enable_shared_from_this example
#include <iostream>
#include <memory>
struct C : std::enable_shared_from_this<C> {};
struct D : public C {};
int main () {
std::shared_ptr<D> foo, bar;
foo = std::make_shared<D>();
bar = foo->shared_from_this();
return 0;
}
Compiler complains:
In file included from /usr/include/c++/4.9/bits/shared_ptr.h:52:0,
from /usr/include/c++/4.9/memory:82,
from 3:
/usr/include/c++/4.9/bits/shared_ptr_base.h: In instantiation of 'std::__shared_ptr<_Tp, _Lp>& std::__shared_ptr<_Tp, _Lp>::operator=(std::__shared_ptr<_Tp1, _Lp>&&) [with _Tp1 = C; _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]':
/usr/include/c++/4.9/bits/shared_ptr.h:299:4: required from 'std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp1>&&) [with _Tp1 = C; _Tp = D]'
14:7: required from here
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: error: no matching function for call to 'std::__shared_ptr<D, (__gnu_cxx::_Lock_policy)2u>::__shared_ptr(std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type)'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: candidates are:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1145:7: note: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__weak_ptr<_Tp, _Lp>&, std::nothrow_t) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
__shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:1145:7: note: candidate expects 2 arguments, 1 provided
/usr/include/c++/4.9/bits/shared_ptr_base.h:1087:2: note: template<class _Alloc, class ... _Args> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...)
__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:1087:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: cannot convert 'std::move<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>((* & __r))' (type 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}') to type 'std::_Sp_make_shared_tag'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:967:17: note: constexpr std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u; std::nullptr_t = std::nullptr_t]
constexpr __shared_ptr(nullptr_t) noexcept
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:967:17: note: no known conversion for argument 1 from 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' to 'std::nullptr_t'
/usr/include/c++/4.9/bits/shared_ptr_base.h:963:2: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Up>&&)
__shared_ptr(std::auto_ptr<_Tp1>&& __r);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:963:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' is not derived from 'std::auto_ptr<_Up>'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:951:2: note: template<class _Tp1, class _Del> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::unique_ptr<_Up, _Ep>&&)
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:951:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' is not derived from 'std::unique_ptr<_Tp, _Dp>'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:939:11: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__weak_ptr<_Tp1, _Lp>&)
explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:939:11: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' is not derived from 'const std::__weak_ptr<_Tp>'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:931:2: note: template<class _Tp1, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::__shared_ptr<_Tp1, _Lp>&&)
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:931:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:929:31: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<typename _Tp1, typename = typename
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:922:7: note: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::__shared_ptr<_Tp, _Lp>&&) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
__shared_ptr(__shared_ptr&& __r) noexcept
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:922:7: note: no known conversion for argument 1 from 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' to 'std::__shared_ptr<D, (__gnu_cxx::_Lock_policy)2u>&&'
/usr/include/c++/4.9/bits/shared_ptr_base.h:918:2: note: template<class _Tp1, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp1, _Lp>&)
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:918:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:916:31: error: no type named 'type' in 'struct std::enable_if<false, void>'
template<typename _Tp1, typename = typename
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:912:7: note: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp, _Lp>&) [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
__shared_ptr(const __shared_ptr&) noexcept = default;
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:912:7: note: no known conversion for argument 1 from 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}' to 'const std::__shared_ptr<D, (__gnu_cxx::_Lock_policy)2u>&'
/usr/include/c++/4.9/bits/shared_ptr_base.h:908:2: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp1, _Lp>&, _Tp*)
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:908:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: candidate expects 2 arguments, 1 provided
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:903:9: note: template<class _Deleter, class _Alloc> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t, _Deleter, _Alloc)
__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:903:9: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: cannot convert 'std::move<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>((* & __r))' (type 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}') to type 'std::nullptr_t'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:898:2: note: template<class _Deleter> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t, _Deleter)
__shared_ptr(nullptr_t __p, _Deleter __d)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:898:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: cannot convert 'std::move<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>((* & __r))' (type 'std::remove_reference<std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>}') to type 'std::nullptr_t'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:889:2: note: template<class _Tp1, class _Deleter, class _Alloc> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter, _Alloc)
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:889:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: mismatched types '_Tp1*' and 'std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:880:2: note: template<class _Tp1, class _Deleter> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter)
__shared_ptr(_Tp1* __p, _Deleter __d)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:880:2: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: mismatched types '_Tp1*' and 'std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:870:11: note: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*)
explicit __shared_ptr(_Tp1* __p)
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:870:11: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/shared_ptr_base.h:1001:4: note: mismatched types '_Tp1*' and 'std::__shared_ptr<C, (__gnu_cxx::_Lock_policy)2u>'
__shared_ptr(std::move(__r)).swap(*this);
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:865:17: note: constexpr std::__shared_ptr<_Tp, _Lp>::__shared_ptr() [with _Tp = D; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
constexpr __shared_ptr() noexcept
^
/usr/include/c++/4.9/bits/shared_ptr_base.h:865:17: note: candidate expects 0 arguments, 1 provided
It is inherited:
// enable_shared_from_this example
#include <iostream>
#include <memory>
struct C : std::enable_shared_from_this<C> {};
struct D : public C {};
int main () {
std::shared_ptr<D> foo;
foo = std::make_shared<D>();
std::shared_ptr<C> bar = foo->shared_from_this();
return 0;
}
You define the shared_from_this in the class C: so the object returns std::shated_ptr<C>. No surprise. You still may downcast it to std::shared_ptr<D> with std::dynamic_pointer_cast.
As #DimityKuzminov already pointed out, shared_from_this() will always return a std::shared_pointer<C> also when called from std::shared_ptr<D>. In order to use std::dynmaic_pointer_cast your base also needs to have a virtual function like a virtual destructor (otherwise you compiler will tell you source type is not polymorphic). Here is an example:
// enable_shared_from_this example
#include <iostream>
#include <memory>
struct C : std::enable_shared_from_this<C> {
virtual ~C() = default;
};
template<typename T, typename U>
std::shared_ptr<T>
shared_from(const std::shared_ptr<U> &a)
{
return std::dynamic_pointer_cast<T>(a->shared_from_this());
}
struct D : public C {};
int main () {
std::shared_ptr<D> foo, bar;
foo = std::make_shared<D>();
bar = shared_from<D>(foo);
return 0;
}
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.
I'm not clear why it is legal to assign tuple<X,Y>=pair<X,Y>
But it is illegal to assign pair<X,Y>=tuple<X,Y>
std::pair<int, double> x { 1 , 5.5};
std::tuple<int, double> y { 1 , 5.5};
int a;
double b;
std::tie(a,b) = x;
std::tie(a,b) = y;
x = y; // THIS LINE (line 12)
y = x; // but this is fine ???
Shouldn't this be symmetrical?
Using g++ 4.8.1 gives the following errors:
tp.cpp:12:4: error: no match for operator= (operand types are std::pair<int, double> and std::tuple<int, double>)
x = y;
^
tp.cpp:12:4: note: candidates are:
In file included from /opt/gcc-4.8.1/include/c++/4.8.1/utility:70:0,
from /opt/gcc-4.8.1/include/c++/4.8.1/tuple:38,
from tp.cpp:1:
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:158:7: note: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = double]
operator=(const pair& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:158:7: note: no known conversion for argument 1 from std::tuple<int, double> to const std::pair<int, double>&
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:166:7: note: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = int; _T2 = double]
operator=(pair&& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:166:7: note: no known conversion for argument 1 from std::tuple<int, double> to std::pair<int, double>&&
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:177:2: note: template<class _U1, class _U2> std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(const std::pair<_U1, _U2>&) [with _U1 = _U1; _U2 = _U2; _T1 = int; _T2 = double]
operator=(const pair<_U1, _U2>& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:177:2: note: template argument deduction/substitution failed:
tp.cpp:12:4: note: std::tuple<int, double> is not derived from const std::pair<_T1, _T2>
x = y;
^
In file included from /opt/gcc-4.8.1/include/c++/4.8.1/utility:70:0,
from /opt/gcc-4.8.1/include/c++/4.8.1/tuple:38,
from tp.cpp:1:
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:186:2: note: template<class _U1, class _U2> std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_U1, _U2>&&) [with _U1 = _U1; _U2 = _U2; _T1 = int; _T2 = double]
operator=(pair<_U1, _U2>&& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:186:2: note: template argument deduction/substitution failed:
tp.cpp:12:4: note: std::tuple<int, double> is not derived from std::pair<_T1, _T2>
x = y;
^
I think this is another case of:
No one proposed it.
Fwiw, your code works with libc++ (as an extension). libc++ implemented a "tuple-like" concept which includes tuple, pair and array, and then has member templates (on tuple and pair) that operate on "tuple-like" types. The approach hasn't been completely without problems, but it does seem promising.
I'm not clear why it is legal to assign tuple<X,Y>=pair<X,Y>
But it is illegal to assign pair<X,Y>=tuple<X,Y>
std::pair<int, double> x { 1 , 5.5};
std::tuple<int, double> y { 1 , 5.5};
int a;
double b;
std::tie(a,b) = x;
std::tie(a,b) = y;
x = y; // THIS LINE (line 12)
y = x; // but this is fine ???
Shouldn't this be symmetrical?
Using g++ 4.8.1 gives the following errors:
tp.cpp:12:4: error: no match for operator= (operand types are std::pair<int, double> and std::tuple<int, double>)
x = y;
^
tp.cpp:12:4: note: candidates are:
In file included from /opt/gcc-4.8.1/include/c++/4.8.1/utility:70:0,
from /opt/gcc-4.8.1/include/c++/4.8.1/tuple:38,
from tp.cpp:1:
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:158:7: note: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = double]
operator=(const pair& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:158:7: note: no known conversion for argument 1 from std::tuple<int, double> to const std::pair<int, double>&
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:166:7: note: std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = int; _T2 = double]
operator=(pair&& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:166:7: note: no known conversion for argument 1 from std::tuple<int, double> to std::pair<int, double>&&
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:177:2: note: template<class _U1, class _U2> std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(const std::pair<_U1, _U2>&) [with _U1 = _U1; _U2 = _U2; _T1 = int; _T2 = double]
operator=(const pair<_U1, _U2>& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:177:2: note: template argument deduction/substitution failed:
tp.cpp:12:4: note: std::tuple<int, double> is not derived from const std::pair<_T1, _T2>
x = y;
^
In file included from /opt/gcc-4.8.1/include/c++/4.8.1/utility:70:0,
from /opt/gcc-4.8.1/include/c++/4.8.1/tuple:38,
from tp.cpp:1:
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:186:2: note: template<class _U1, class _U2> std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_U1, _U2>&&) [with _U1 = _U1; _U2 = _U2; _T1 = int; _T2 = double]
operator=(pair<_U1, _U2>&& __p)
^
/opt/gcc-4.8.1/include/c++/4.8.1/bits/stl_pair.h:186:2: note: template argument deduction/substitution failed:
tp.cpp:12:4: note: std::tuple<int, double> is not derived from std::pair<_T1, _T2>
x = y;
^
I think this is another case of:
No one proposed it.
Fwiw, your code works with libc++ (as an extension). libc++ implemented a "tuple-like" concept which includes tuple, pair and array, and then has member templates (on tuple and pair) that operate on "tuple-like" types. The approach hasn't been completely without problems, but it does seem promising.
I have the following unordered_map, that maps a pointer to an object of type Item with a key of type int.
typedef std::unordered_map<int, Item*> ItemList;
ItemList Items;
However, in my addItem method, I receive a strange error at compilation.
void ItemManager::addItem(Item *it) {
int i = it->getItemID();
Items.insert(ItemList::value_type(i, *it));
}
Yields:
item_manager.cc: In member function ‘void ItemManager::addItem(Item*)’:
item_manager.cc:31:51: error: no matching function for call to ‘std::pair<const int, Item*>::pair(int&, Item&)’
item_manager.cc:31:51: note: candidates are:
/usr/include/c++/4.6/bits/stl_pair.h:140:2: note: template<class ... _Args1, class ... _Args2> std::pair::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)
/usr/include/c++/4.6/bits/stl_pair.h:135:2: note: template<class _U1, class _U2> std::pair::pair(std::pair<_U1, _U2>&&)
/usr/include/c++/4.6/bits/stl_pair.h:131:2: note: template<class _U1, class _U2, class> std::pair::pair(_U1&&, _U2&&)
/usr/include/c++/4.6/bits/stl_pair.h:125:2: note: template<class _U2, class> std::pair::pair(const _T1&, _U2&&)
/usr/include/c++/4.6/bits/stl_pair.h:120:2: note: template<class _U1, class> std::pair::pair(_U1&&, const _T2&)
/usr/include/c++/4.6/bits/stl_pair.h:112:17: note: constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int, _T2 = Process*, std::pair<_T1, _T2> = std::pair<const int, Process*>]
/usr/include/c++/4.6/bits/stl_pair.h:112:17: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.6/bits/stl_pair.h:108:21: note: template<class _U1, class _U2> constexpr std::pair::pair(const std::pair<_U1, _U2>&)
/usr/include/c++/4.6/bits/stl_pair.h:103:26: note: constexpr std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = const int, _T2 = Process*]
/usr/include/c++/4.6/bits/stl_pair.h:103:26: note: no known conversion for argument 2 from ‘Process’ to ‘Process* const&’
/usr/include/c++/4.6/bits/stl_pair.h:99:26: note: constexpr std::pair<_T1, _T2>::pair() [with _T1 = const int, _T2 = Process*]
/usr/include/c++/4.6/bits/stl_pair.h:99:26: note: candidate expects 0 arguments, 2 provided
Any ideas what could be causing these errors? I'm new to C++, so I have been working off of examples of unordered_maps I've found around the web. Any help is greatly appreciated. Please and thank you!
The values in your map are of type Item*, so you need to insert Item*, not Item. This line
Items.insert(ItemList::value_type(i, *it));
should be
Items.insert(ItemList::value_type(i, it));
You don't need to dereference the pointer:
void ItemManager::addItem(Item *it) {
int i = it->getItemID();
Items.insert(ItemList::value_type(i, it));
}