std::pair 结合 const std:unique_ptr 给出 "no matching function call" 错误
std::pair gives "no matching function call" error in combination with const std:unique_ptr
我偶然发现了我不理解的 std::make_pair 行为。给定以下代码
#include <iostream>
using namespace std;
#include <memory>
#include <utility>
class TestClass
{
public:
TestClass(const std::string& str) : str{std::make_unique<const std::string>(str)} {};
~TestClass() = default; // (1)
private:
std::unique_ptr<const std::string> str{}; // (2)
// const std::unique_ptr<const std::string> str{}; // (3)
};
int main()
{
// is fine all the time
TestClass myTestClass = TestClass("myTestClass"); // (4)
// doesn't work at all
std::make_pair("myTestClassKey", myTestClass); // (5)
// works, but only wit (1) commented out and (2) instead of (3)
std::make_pair("myTestClassKey", TestClass("myTestClass")); // (6)
return 0;
}
TestClass
中的第 (1) 至 (3) 行让我很头疼。尽管第 (4) 行的工作与第 (1) 和 (2) 或 (3) 行的注释无关,但第 (5) 行根本不起作用,而第 (6) 行仅在第 (1) 行被注释掉且第 (2) 行时编译) 代替第 (3) 行。我收到的编译器错误总是类似于:
||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
/usr/include/c++/9/bits/stl_pair.h||In instantiation of ‘constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = const char (&)[15]; _T2 = TestClass; typename std::__decay_and_strip<_T2>::__type = TestClass; typename std::__decay_and_strip<_Tp>::__type = const char*]’:|
/home/johndoe/Coding/test/main.cpp|26|required from here|
/usr/include/c++/9/bits/stl_pair.h|529|error: no matching function for call to ‘std::pair<const char*, TestClass>::pair(const char [15], TestClass)’|
/usr/include/c++/9/bits/stl_pair.h|436|note: candidate: ‘template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)’|
/usr/include/c++/9/bits/stl_pair.h|436|note: template argument deduction/substitution failed:|
/usr/include/c++/9/bits/stl_pair.h|529|note: mismatched types ‘std::tuple<_Tps ...>’ and ‘const char [15]’|
/usr/include/c++/9/bits/stl_pair.h|375|note: candidate: ‘template<class ... _Args1, class ... _Args2> std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)’|
...
/usr/include/c++/9/bits/stl_pair.h|529|note: candidate expects 0 arguments, 2 provided|
||=== Build failed: 9 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
简而言之,这是为什么?到目前为止我唯一的想法是它可能与 std::unique_ptr 的移动/复制构造有关?但是为什么第(1)行会引起麻烦呢?
让我们分解一下您的代码的作用:
~TestClass() = default; // (1)
您将析构函数明确定义为默认析构函数。这算作用户声明的析构函数。
std::unique_ptr<const std::string> str{}; // (2)
声明一个非常量 unique_ptr
字段。该字段可以改变,因此从中移出。
// const std::unique_ptr<const std::string> str{}; // (3)
声明一个常量 unique_ptr
字段。对象初始化后,您将不能离开该字段。
TestClass myTestClass = TestClass("myTestClass"); // (4)
通过复制省略直接初始化 myTestClass
。这意味着这里没有 copy-/move-constructor 或赋值发生。 (https://en.cppreference.com/w/cpp/language/copy_elision)
std::make_pair("myTestClassKey", myTestClass); // (5)
创建一个 std::pair
,将 myTestClass
的副本作为第二个值。 TestClass
无法复制 - 没有定义隐式复制构造函数,因为 unique_ptr
也没有!
std::make_pair("myTestClassKey", TestClass("myTestClass")); // (6)
用纯右值(“纯”右值)初始化 std::pair
,它是表达式 TestClass("myTestClass")
的结果。这种类型的初始化需要一个可用的移动构造函数。为您自动定义隐式声明的移动构造函数,前提是:
- 没有用户声明的复制构造函数;
- 没有用户声明的复制赋值运算符;
- 没有用户声明的移动赋值运算符;
- 没有用户声明的析构函数。
(https://en.cppreference.com/w/cpp/language/move_constructor)
显式默认的析构函数 (1) 被算作用户声明的析构函数,这意味着当 (1) 未注释时不会发出隐式声明的移动构造函数,因此 (6) 出现编译错误。
我偶然发现了我不理解的 std::make_pair 行为。给定以下代码
#include <iostream>
using namespace std;
#include <memory>
#include <utility>
class TestClass
{
public:
TestClass(const std::string& str) : str{std::make_unique<const std::string>(str)} {};
~TestClass() = default; // (1)
private:
std::unique_ptr<const std::string> str{}; // (2)
// const std::unique_ptr<const std::string> str{}; // (3)
};
int main()
{
// is fine all the time
TestClass myTestClass = TestClass("myTestClass"); // (4)
// doesn't work at all
std::make_pair("myTestClassKey", myTestClass); // (5)
// works, but only wit (1) commented out and (2) instead of (3)
std::make_pair("myTestClassKey", TestClass("myTestClass")); // (6)
return 0;
}
TestClass
中的第 (1) 至 (3) 行让我很头疼。尽管第 (4) 行的工作与第 (1) 和 (2) 或 (3) 行的注释无关,但第 (5) 行根本不起作用,而第 (6) 行仅在第 (1) 行被注释掉且第 (2) 行时编译) 代替第 (3) 行。我收到的编译器错误总是类似于:
||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
/usr/include/c++/9/bits/stl_pair.h||In instantiation of ‘constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = const char (&)[15]; _T2 = TestClass; typename std::__decay_and_strip<_T2>::__type = TestClass; typename std::__decay_and_strip<_Tp>::__type = const char*]’:|
/home/johndoe/Coding/test/main.cpp|26|required from here|
/usr/include/c++/9/bits/stl_pair.h|529|error: no matching function for call to ‘std::pair<const char*, TestClass>::pair(const char [15], TestClass)’|
/usr/include/c++/9/bits/stl_pair.h|436|note: candidate: ‘template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)’|
/usr/include/c++/9/bits/stl_pair.h|436|note: template argument deduction/substitution failed:|
/usr/include/c++/9/bits/stl_pair.h|529|note: mismatched types ‘std::tuple<_Tps ...>’ and ‘const char [15]’|
/usr/include/c++/9/bits/stl_pair.h|375|note: candidate: ‘template<class ... _Args1, class ... _Args2> std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)’|
...
/usr/include/c++/9/bits/stl_pair.h|529|note: candidate expects 0 arguments, 2 provided|
||=== Build failed: 9 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
简而言之,这是为什么?到目前为止我唯一的想法是它可能与 std::unique_ptr 的移动/复制构造有关?但是为什么第(1)行会引起麻烦呢?
让我们分解一下您的代码的作用:
~TestClass() = default; // (1)
您将析构函数明确定义为默认析构函数。这算作用户声明的析构函数。
std::unique_ptr<const std::string> str{}; // (2)
声明一个非常量 unique_ptr
字段。该字段可以改变,因此从中移出。
// const std::unique_ptr<const std::string> str{}; // (3)
声明一个常量 unique_ptr
字段。对象初始化后,您将不能离开该字段。
TestClass myTestClass = TestClass("myTestClass"); // (4)
通过复制省略直接初始化 myTestClass
。这意味着这里没有 copy-/move-constructor 或赋值发生。 (https://en.cppreference.com/w/cpp/language/copy_elision)
std::make_pair("myTestClassKey", myTestClass); // (5)
创建一个 std::pair
,将 myTestClass
的副本作为第二个值。 TestClass
无法复制 - 没有定义隐式复制构造函数,因为 unique_ptr
也没有!
std::make_pair("myTestClassKey", TestClass("myTestClass")); // (6)
用纯右值(“纯”右值)初始化 std::pair
,它是表达式 TestClass("myTestClass")
的结果。这种类型的初始化需要一个可用的移动构造函数。为您自动定义隐式声明的移动构造函数,前提是:
- 没有用户声明的复制构造函数;
- 没有用户声明的复制赋值运算符;
- 没有用户声明的移动赋值运算符;
- 没有用户声明的析构函数。 (https://en.cppreference.com/w/cpp/language/move_constructor)
显式默认的析构函数 (1) 被算作用户声明的析构函数,这意味着当 (1) 未注释时不会发出隐式声明的移动构造函数,因此 (6) 出现编译错误。