c++ - 尝试 'replicate' shared_ptr 向上转换行为导致复制构造函数无限递归(导致段错误)

标签 c++ templates c++17 template-meta-programming

我正在尝试复制 shared_ptr 行为以更好地理解 c++17 中的模板元编程和 type_traits。 具体来说,我想复制向上转换行为,即分配/复制创建的机会 shared_ptr< Derived >shared_ptr< Base >没有任何显式转换。

类型检查工作正常,但在尝试复制或分配派生对象时,我在复制构造函数中遇到无限循环的段错误。

通用模板类

#pragma once

#include <memory>
#include <type_traits>

template <typename T>
class Generic {
    public:
        template <typename DerivedT>
        using Assignable = typename std::enable_if<std::is_assignable<T, DerivedT>::value, Generic<T> &>::type;

        Generic() : _ptr(nullptr) {}


        Generic(T *ptr) : _ptr{ptr} {};

        Generic(Generic && cptr) :
                _ptr(std::move(cptr._ptr))
        {}

        Generic(const Generic & cptr) :
                _ptr{cptr._ptr}
        {}

        template <typename DerivedT, typename = Assignable<DerivedT>>
        Generic(const Generic<DerivedT> &cptr) 
            : Generic(static_cast<const Generic &>(cptr)._ptr)
        {}

        ~Generic() = default;

        Generic & operator=(Generic && cptr) = default;

        Generic & operator=(const Generic & cptr) {
            _ptr = cptr._ptr;
            return *this;
        }

        template <typename DerivedT>
        Assignable<DerivedT> operator=(const Generic<DerivedT> &cptr) {
            _ptr = static_cast<const Generic &>(cptr)._ptr;
            return *this;
        }

    private:
        T* _ptr;
};

主要.cpp

#include "Generic.hpp"

struct Base {
};

struct Derived : public Base {
};

int main() {
    Generic<Derived> derived = Generic<Derived>();
    Generic<Base> base(derived);
    //Generic<Base> base = derived;
}

最佳答案

您的问题可以简化为:

template <typename T>
class Generic {
    public:
        Generic() = default;

        Generic(T *ptr) : _ptr{ptr} {};

        template <typename Derived>
        Generic(const Generic<Derived> &cptr) :
          Generic(static_cast<const Generic &>(cptr)._ptr)
        {}

    private:
        T* _ptr = nullptr;
};

struct Base {
};

struct Derived : public Base {
};

int main() {
    Generic<Derived> derived = Generic<Derived>();
    Generic<Base> base(derived);
}

问题是 static_cast<const Generic &>(cptr)您正在隐式创建 Generic<T> 的实例表格 Generic<Derived> ,因此递归地调用构造函数无限

一个可能的修复是:

template <typename T>
class Generic {
    public:
        Generic() = default;

        Generic(T *ptr) : _ptr{ptr} {};

        template <typename Derived>
        Generic(const Generic<Derived> &cptr) :
          Generic(cptr._ptr)
        {}

    private:
        T* _ptr = nullptr;

    template <typename U>
    friend class Generic;
};

struct Base {
};

struct Derived : public Base {
};

int main() {
    Generic<Derived> derived = Generic<Derived>();
    Generic<Base> base(derived);
}

关于c++ - 尝试 'replicate' shared_ptr 向上转换行为导致复制构造函数无限递归(导致段错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56456882/

相关文章:

c++ - "main"函数可以用 "noexcept"说明符声明吗?

c++ - 在 C++ 中将数组元素解包到多个变量的规则是什么?

c++ - 模板忽略 [[nodiscard]] 属性

c++ - constexpr exp、log、pow

c++ - “Expression must have class type”错误,尝试调用类函数

c++ - 在编译时计算迭代器返回类型

c++ - const 引用的类型是什么?

c++ - Lambda 函数 - 按值捕获

c++ - 从字符串文字到 char * 的转换

c++ - 启用 C++11 时如何修复 'wrong number of template arguments''?