【问题标题】:std::pair gives "no matching function call" error in combination with const std:unique_ptrstd::pair 结合 const std:unique_ptr 给出“没有匹配的函数调用”错误
【发布时间】:2021-11-30 00:29:37
【问题描述】:

我偶然发现了我不理解的 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)行会引起麻烦呢?

【问题讨论】:

  • 请发布实际代码,而不是需要我们删除一些// 的代码。您发布的代码无法编译,因为该类没有名为 str 的成员
  • 已修复,抱歉!

标签: c++ destructor smart-pointers std-pair


【解决方案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。这意味着这里没有发生复制/移动构造函数或赋值。 (https://en.cppreference.com/w/cpp/language/copy_elision)

std::make_pair("myTestClassKey", myTestClass);  // (5)

使用myTestClass 的副本作为第二个值创建std::pair。 TestClass 无法复制 - 没有定义隐式复制构造函数,因为 unique_ptr 也没有!

std::make_pair("myTestClassKey", TestClass("myTestClass"));  // (6)

使用纯右值(“纯”右值)初始化std::pair,它是表达式TestClass("myTestClass") 的结果。这种类型的初始化需要一个可用的移动构造函数。一个隐式声明的移动构造函数会自动为您定义,前提是:

显式默认的析构函数 (1) 被算作用户声明的析构函数,这意味着当 (1) 未注释时不会发出隐式声明的移动构造函数,因此为什么会出现 (6) 上的编译错误。

【讨论】:

  • 啊,现在我明白了!总结一下: - (3) 在这种情况下永远不会工作,因为智能指针不能被改变 - (5) 在这种情况下永远不会工作,因为唯一的指针不能被复制 - (6) 与 (1) 一起工作出,因为隐式提供了移动构造函数 - 如果我显式实现移动构造函数,(6)将与(1)未注释一起使用对吗?在这方面,除非有很好的理由,否则最好不要显式定义默认构造函数/析构函数?
  • 正确。有关何时使用 =default 的信息,请参阅 stackoverflow.com/a/56801243/3514205。
猜你喜欢
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 2022-01-19
  • 2020-10-21
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多