Clang 和 gcc 因模板函数重载而陷入困境

问题描述 投票:0回答:1

我必须从抽象基类 Base 派生类 Derived1 和 Derived2。我还有一个 Container 类,其中包含指向基类对象的唯一指针的映射,因为我想要执行运行时多态性。 Container 类有一个函数“add”,它采用指向基类对象的唯一指针并将其添加到映射中。我注意到我经常知道所添加对象的具体类型,因此我添加了一个重载的模板化 add 函数,该函数按值获取任意对象,将其移动到唯一的指针中并调用另一个 add 函数。 这是一个最小的例子:

#include <map>
#include <memory>
#include <string>

class Base {
    public:
        virtual ~Base();
};

class Derived1 : Base {
};

class Derived2 : Base {
};

class Container {
    public:
        std::map<std::string, std::unique_ptr<Base>> coll;

        void add(std::string name, std::unique_ptr<Base> elem) {
            coll.emplace(name, std::move(elem));
        }

        template<typename T>
        void add(std::string name, T elem) {
            this->add(name, std::make_unique<T>(std::move(elem)));
        }
};

int main() {
    Container c;

    //a little more convenient than c.add("1", std::make_unique<Derived1>());
    c.add("1", Derived1()); 
}

当尝试用 clang 16 编译它时,它似乎被卡住了,并且慢慢地使用越来越多的 RAM,直到我的 32GB 已满。 gcc 似乎也被卡住了,但没有使用越来越多的 RAM。

我可以通过重命名其中一个添加函数来修复它,但我仍然很好奇这里发生了什么。

这是预期的行为吗?因为我违反了一些你必须知道的不祥的 C++ 规则?我认为无论输入如何,编译器陷入困境都是不应该真正发生的事情。

因此,要么我做了一些在其他代码库中不会发生的事情,所以这个编译器错误从未被注意到,要么我做了一些非常不寻常的事情,以至于除了编译器被卡住之外,没有人费心去制定一个更干净的解决方案。这是我的第二个问题:他们是否认为我的方法如此不惯用,以至于这对其他人来说似乎不成问题?

c++ templates inheritance overloading unique-ptr
1个回答
1
投票

该方法模板:

template<typename T>
void add(std::string name, T elem) {
     this->add(name, std::make_unique<T>(std::move(elem)));
}

导致实例化的无限循环。

称为首字母缩写

T
=
Derived1
,
然后
T
=
std::uqniue_ptr<Derived1>
,
然后
T
=
std::uqniue_ptr<std::unique_ptr<Derived1>>
,
等等。

编译器不断实例化这些不同的方法,直到最终耗尽内存。

© www.soinside.com 2019 - 2024. All rights reserved.