首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有CRTP类的std::make_pair调用中的奇怪行为

带有CRTP类的std::make_pair调用中的奇怪行为
EN

Stack Overflow用户
提问于 2022-03-16 15:06:15
回答 1查看 85关注 0票数 -1

问题

我有一个简单的CRTP模式类BaseInterface,以及从这个类派生的两个类:test_dinttest_dint2

test_dinttest_dint2 - in test_dint dtor之间的差异显式声明为~test_dint() = default;

我尝试通过调用<std::intptr_t, test_dint>使std::结对类型为std::make_pair,而编译失败时出错:

  • MSVC - error C2440: '<function-style-cast>': cannot convert from 'initializer list' to '_Mypair'
  • CLang 11 - error: no matching constructor for initialization of '__pair_type' (aka 'pair<long, test_dint>')

但是,如果类型对更改为<std::intptr_t, test_dint2> -所有编译都没有错误。

我不明白为什么显式的dtor声明会改变std::结对模板的行为?

全码

代码语言:javascript
运行
复制
#include <memory>
#include <unordered_map>

template<typename DerivedT>
class enable_down_cast
{  
public:
    DerivedT const& impl() const
    {
        // casting "down" the inheritance hierarchy
        return *static_cast<DerivedT const*>(this);
    }

    DerivedT& impl()
    {
        return *static_cast<DerivedT*>(this);
    }

    //~enable_down_cast() = default;

protected:
    // disable deletion of Derived* through Base*
    // enable deletion of Base* through Derived*
    ~enable_down_cast() = default;

private:  
    using Base = enable_down_cast;  
};

template<typename Impl>
class BaseInterface : public enable_down_cast<Impl>
{
public:
    using handle_type = std::intptr_t;

    BaseInterface() = default;

    // Disable copy
    BaseInterface(const BaseInterface&) = delete;
    BaseInterface& operator=(const BaseInterface&) = delete;

    // Enable move
    BaseInterface(BaseInterface&&) = default;
    BaseInterface& operator=(BaseInterface&&) = default;

    ~BaseInterface() = default;

    handle_type handle() const
    {
        return m_handle;
    }

protected:
    handle_type m_handle{ 0 };

private:
    using enable_down_cast<Impl>::impl;
};

class test_dint : public BaseInterface<test_dint> {
public:
    test_dint() = delete;
    test_dint(const handle_type handle) : 
        BaseInterface<test_dint>()
    {
        m_handle = handle;
    }
    ~test_dint() = default;
};

class test_dint2 : public BaseInterface<test_dint2> {
public:
    test_dint2() = delete;
    test_dint2(const handle_type handle) : 
        BaseInterface<test_dint2>()
    {
        m_handle = handle;
    }
};


int main()
{
    test_dint::handle_type handle = 100500;
    std::make_pair(handle, test_dint{ handle }); // <--- failed ctor
    std::make_pair(handle, test_dint2{ handle });
    return 0;
}

现场演示

https://godbolt.org/z/eee7h47v7

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-16 15:48:42

这是因为当您声明析构函数时,您是防止编译器生成移动构造函数,所以test_dint不再是moveconstructable (也不能复制,因为它是基本的)。

显式声明它将使其工作。

代码语言:javascript
运行
复制
test_dint(test_dint&&)=default;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71499469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档