如何在标题中公开引用变量?

时间:2016-06-13 08:22:32

标签: c++ reference header-files

为了方便起见,我正试图在cParamIDsByAge的一侧创建引用变量boost::bimap

尝试#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

然后我尝试直接在标题中定义引用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

我没有初始化标题中的引用:

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;

编译器抱怨头文件:

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

3 个答案:

答案 0 :(得分:4)

错误消息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类型。您无法在auto声明中使用extern,因为没有可以推断出的初始值设定项。

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都拒绝它。

答案 1 :(得分:2)

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

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

这是正确地声明参考变量。其余的应该按原样运作。

答案 2 :(得分:1)

解决方案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; }