首页 > 解决方案 > 复制构造函数和带有 std::any 的构造函数之间的冲突

问题描述

我正在测试 c++17 的 std:any 功能,这似乎解决了我项目中的许多类型问题。尽管如此,我已经走到了死胡同……

看看这个示例(工作)代码:

#include <any>
#include <string>
#include <iostream>
#include <vector>

class Test
{
public:
    Test(const Test &o) : name(o.name), data(o.data) { std::cout << "copy constructor" << std::endl; };
    Test(std::string name, const char *data) : name(name), data(data) { std::cout << "string-constchar constructor" << std::endl; }
    Test(std::string name, std::any data) : name(name), data(data) { std::cout << "string-any constructor" << std::endl; }
    explicit Test(std::any data) : data(data) { std::cout << "any constructor" << std::endl; }

    std::string name;
    std::any data;
};

int main()
{
    Test t1("test", "test 2");
    Test t2("test", 57);
    Test t3 = t1;
    Test t4(97);
    // std::vector<Test> vt;
    // vt.push_back(t3);

    return 0;
}

如果我们在 g++9 下编译和运行这段代码,我们会发现我们中的许多人可能会期待:

string-constchar constructor
string-any constructor
copy constructor
any constructor

有趣的是,编译器如何能够完美地识别 thestd::any和 the之间的区别const char*并调用正确的构造函数。

但是,它提出了许多处理复制构造函数的问题。例如,如果explicit使用 param 从构造函数中删除关键字std::any,它将立即与复制构造函数发生冲突,并且编译器 (clang-9 / g++9) 将报告编译错误。

当 2 条注释线(矢量线)未注释时,也会发生同样的情况。push_back/emplace_back 可能会在某些时候调用复制构造函数,这再次触发与复制构造函数之间的冲突相关的编译错误。

我对为什么编译器无法处理复制构造函数的情况(但其他人没有任何问题)感到很迷茫。关于为什么会发生这种情况的任何想法?任何可能的解决方法?

谢谢!

标签: c++c++17

解决方案


当你有这样的事情:

struct X {
    X();
    X(std::any);
};

X a;
X b = a;

当我们试图弄清楚如何处理 的复制时b,我们有复制构造函数,但我们也有X(std::any)哪个是可行的,如果X是可复制构造的,要检查它,我们必须递归检查是否X可以构造再次让我们 X进入X(std::any)构造函数。

现在,有趣的是,libc++ 的实现在std::any这里可以工作,而 libstdc++ 的却不行。这似乎完全取决于何时实例化相关类型特征以及实现如何处理缓存它们 - 我不确定。另见gcc 错误 90415跟踪此。


推荐阅读