引用已放置的映射值需要定义类

Reference to emplaced map values requires definition of class

本文关键字:定义 映射 引用      更新时间:2023-10-16

我需要改变在我正在处理的较大项目中包含头的方式。我可以用较小的单个程序模拟当前出现的错误。

例如,以下编译:

#include <map>
class C;
class A {
public:
    C& add();
    std::map<int,C> Cmap;
    void dosomethingwithC();
};
class B {
public:
    A& add();
    std::map<int,A> Amap;
};
class C {
public:
    B& add();
    std::map<int,B> Bmap;
};
int main()
{
    C c;
    auto& emplacedB = c.add();
    auto& emplacedA = emplacedB.add();
    auto& emplacedC = emplacedA.add();
    emplacedC.add();
    return 0;
}
C& A::add()
{
    auto emplace_results = Cmap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    auto& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;
}
B& C::add()
{
    auto emplace_results = Bmap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    //auto& emplaced_pair = *pair_iterator;
    std::pair<const int,B>& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;
}
A& B::add()
{
    auto emplace_results = Amap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    auto& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;;
}
void A::dosomethingwithC()
{
    Cmap[3].add();
}

但是,如果我将A的函数定义移到更接近A的位置,则以下内容不会编译:

#include <map>
class C;
class A {
public:
    C& add();
    std::map<int,C> Cmap;
    void dosomethingwithC();
};
C& A::add()
{
    auto emplace_results = Cmap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    auto& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;
}
class B {
public:
    A& add();
    std::map<int,A> Amap;
};
class C {
public:
    B& add();
    std::map<int,B> Bmap;
};
int main()
{
    C c;
    auto& emplacedB = c.add();
    auto& emplacedA = emplacedB.add();
    auto& emplacedC = emplacedA.add();
    emplacedC.add();
    return 0;
}
B& C::add()
{
    auto emplace_results = Bmap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    //auto& emplaced_pair = *pair_iterator;
    std::pair<const int,B>& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;
}
A& B::add()
{
    auto emplace_results = Amap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    auto& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;;
}
void A::dosomethingwithC()
{
    Cmap[3].add();
}

即使声明了class C,我也会得到一个错误。该错误解释了std::pair使用未定义class C

构造头和include的正确方法是什么?

方法

  • 所有声明都必须放在标头中,并且
  • 所有的定义都进入.cpp文件
  • 没有一个标头包含彼此

在这个特定的实例中,如果所有.cpp文件都包含所有声明,那么关于丢失定义(对于std::pair,作为std::map的一部分)的错误就会消失。(A需要C,但C需要B)

因此,即使错误是由于缺少定义,也可以通过包含声明来解决。我不知道为什么,我会发布一个单独的问题。

解决方案

A.h

#ifndef A_h
#define A_h
#include <map>
class C;
class A {
public:
    C& add();
    std::map<int,C> Cmap;
    void dosomethingwithC();
};
#endif

B.h

#ifndef B_h
#define B_h
#include <map>
class A;
class B {
public:
    A& add();
    std::map<int,A> Amap;
};
#endif

C.h

#ifndef C_h
#define C_h
#include <map>
class B;
class C {
public:
    B& add();
    std::map<int,B> Bmap;
};
#endif

A.cpp

#include "A.h"
#include "B.h" // also required here
#include "C.h"
C& A::add()
{
    auto emplace_results = Cmap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    auto& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;
}

void A::dosomethingwithC()
{
    Cmap[3].add();
}

B.cpp

#include "A.h"
#include "B.h"
#include "C.h" // also required here
A& B::add()
{
    auto emplace_results = Amap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    auto& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;;
}

C.cpp

#include "A.h" // also required here
#include "B.h"
#include "C.h"
B& C::add()
{
    auto emplace_results = Bmap.emplace(std::piecewise_construct,
        std::forward_as_tuple(3),
        std::forward_as_tuple());
    auto pair_iterator = emplace_results.first;
    //auto& emplaced_pair = *pair_iterator;
    std::pair<const int,B>& emplaced_pair = *pair_iterator;
    auto& map_value = emplaced_pair.second;
    return map_value;
}

主要.cpp

#include "A.h"
#include "B.h"
#include "C.h"
int main()
{
    C c;
    auto& emplacedB = c.add();
    auto& emplacedA = emplacedB.add();
    auto& emplacedC = emplacedA.add();
    emplacedC.add();
    return 0;
}