如何在 header 中公开引用变量?

How to expose a reference variable in a header?

为了方便 (MVCE),我正在尝试在 boost::bimap 的一侧创建一个引用变量 cParamIDsByAge

尝试 #1

code.h

#include <boost/bimap.hpp>

typedef boost::bimap <int, int> ParamIDs;
extern const ParamIDs cParamIDs;
extern auto &cParamIDsByAge = cParamIDs.left;

code.cpp

#include "code.h"

// In my code this inits the variable with some data via a function.
const ParamIDs cParamIDs {};
auto &cParamIDsByAge = cParamIDs.left;

编译器抱怨:

code.h:5:14: warning: ‘cParamIDsByAge’ initialized and declared ‘extern’
extern auto &cParamIDsByAge = cParamIDs.left;
            ^~~~~~~~~~~~~~
code.cpp:4:7: error: conflicting declaration ‘auto& cParamIDsByAge’
auto &cParamIDsByAge = cParamIDs.left;
    ^~~~~~~~~~~~~~
In file included from code.cpp:1:0:
code.h:5:14: note: previous declaration as ‘const boost::bimaps::views::map_view<boost::bimaps::relation::member_at::left, boost::bimaps::detail::bimap_core<int, int, mpl_::na, mpl_::na, mpl_::na> >& cParamIDsByAge’
extern auto &cParamIDsByAge = cParamIDs.left;
            ^~~~~~~~~~~~~~

尝试 #2

然后我尝试直接在header中定义引用cParamIDsByAge

code.h

#include <boost/bimap.hpp>

typedef boost::bimap <int, int> ParamIDs;
extern const ParamIDs cParamIDs;
auto &cParamIDsByAge = cParamIDs.left;

code.cpp

#include "code.h"

const ParamIDs cParamIDs {};

但是抱怨的是:

error: multiple definitions of cParamIDsByAge

尝试 #3

我没有初始化 header 中的引用:

code.h

#include <boost/bimap.hpp>

typedef boost::bimap <int, int> ParamIDs;
extern const ParamIDs cParamIDs;
extern const auto &cParamIDsByAge;

code.cpp

#include "code.h"
const ParamIDs cParamIDs {};
auto &cParamIDsByAge = cParamIDs.left;

编译器抱怨 header 文件:

error: declaration of ‘const auto& cParamIDsByAge’ has no initializer

错误消息 code.h:5:14: warning: ‘cParamIDsByAge’ initialized and declared ‘extern’ 非常简单:在 C++ 中,声明为 extern 的变量可能没有初始值设定项。 (换句话说,extern 可能只出现在声明中,而不是定义中)。

示例用法可能是:

extern int &foo;

// ... cpp file

int bar;
int &foo = bar;

要在您的代码中执行此操作,还有一个问题是您需要将 int 替换为 boost::bimap::left 的类型。您不能在 extern 声明中使用 auto,因为没有可从中推断出的初始化程序。

boost::bimap 碰巧将其定义为 typedef,因此解决方案很简单:

extern ParamIDs::left_map const &x;

// ... in cpp

const ParamIDs c{};
ParamIDs::left_map const &x = c.left;

如果该 typedef 不存在,那么您仍然可以使用 declvaldecltype.

注意 1:我认为标准不清楚 auto const &x = c.left; 是否应该在这里工作,但 gcc 和 clang 都拒绝它。

将 header 中的行更改为以下内容:

// REMOVE: extern auto &cParamIDsByAge = cParamIDs.left;
extern const decltype(cParamIDs.left) &cParamIDsByAge;

这是向前正确声明引用变量。其余的应该按原样工作。

解决方案 1

在头文件中声明cParamIDsByAge的类型,不使用auto,不初始化:

code.h

#include <boost/bimap.hpp>

typedef boost::bimap <int, int> ParamIDs;
extern const ParamIDs cParamIDs;

extern const decltype(cParamIDs.left)& cParamIDsByAge;
// or
extern decltype((cParamIDs.left)) cParamIDsByAge;
// or
extern const ParamIDs::left_map& cParamIDsByAge;

code.cpp

#include "code.h"

const ParamIDs cParamIDs {};
auto &cParamIDsByAge = cParamIDs.left;

解决方案 2

使用函数代替变量:

code.h

#include <boost/bimap.hpp>

typedef boost::bimap <int, int> ParamIDs;
extern const ParamIDs cParamIDs;
inline auto& cParamIDsByAge() { return cParamIDs.left; }