Так что, в общем, это скорее вопрос юриста по теоретическому языку, чем актуальный. Во время борьбы с шаблоном из-за неясной ошибки шаблона я обнаружил поведение, которое не смог объяснить с помощью clang (нижняя строка - нет предупреждения, что я пытаюсь переместить класс, который не может быть перемещен). Странно то, что поведение clang меняется в зависимости от того, присутствует -std=c++17
или нет.
Итак, вот MVP проблемы:
#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;
}
Очевидно, это не будет работать (но поскольку в реальном случае неподвижный класс был членом родительского класса, скрытого глубоко в источниках, без каких-либо предупреждений о том, что он не является подвижным, я не мог сразу понять, что происходит). Поэтому, взяв этот пример на Годболт с -std=c+=17
, вы получите:
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
, который я бы интерпретировал как «эй, я скажу вам, почему вы не можете все то, что на самом деле не хочу, но не то, что движущийся ctor удален ". Как только я меняю -std=c++14
того же диагноза c, но с последующими строками:
<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
, который все еще не упоминает удаленный ход c -тор, но, по крайней мере, указывает мне на виновника. Изначально я подумал, эй, может быть, есть новая перегрузка / семантика для std::make_pair
, которая могла бы вызвать это, но просмотр std :: make_pair не показывает каких-либо соответствующих C ++ 17 изменений. Так это просто странное поведение в диагностике или есть объяснение этому? Просто кур ios.