C ++ 11获取错误'enum-type'没有使用boost 1.59 fileSystem命名类型

时间:2017-07-16 01:10:50

标签: c++11 boost enums

我在用C ++ 11编译代码时遇到错误。 以前的标准它工作正常没有编译问题。 (C ++ 03)

功能签名: boost :: filesystem :: copy_option :: enum_type myFunc()

错误: 'enum class boost :: filesystem :: copy_option'中的'enum-type'没有命名类型

提升版:1.59 编译器:gcc版本:4.8.5

我认为这可能是由于C ++ 11中的枚举类。 但是,我没有任何线索如何解决这个问题。

1 个答案:

答案 0 :(得分:0)

如果我们查看v.1.59.0 Boost Filesystem文档,我们发现boost::filesystem::copy_option定义为:

enum class copy_option
{
  none
  fail_if_exists = none,
  overwrite_if_exists
};

但是enum class是一个C ++ 11的功能,那么包括那个头在C ++ 03模式下是如何工作的呢?让我们看一下标题boost/filesystem/header.hpp,我们在其中copy_option定义了boost::filesystem内的标题:

BOOST_SCOPED_ENUM_START(copy_option)
  {none=0, fail_if_exists = none, overwrite_if_exists};
BOOST_SCOPED_ENUM_END

有点搜索结果表明BOOST_SCOPED_ENUM_STARTBOOST_SCOPED_ENUM_END是Boost.Core库的一部分。 scoped_enum reference page解释说,如果编译器支持该功能,它的目的是生成C ++ 11范围的枚举,否则用C ++ 03构造"来模拟它。它还说不推荐使用BOOST_SCOPED_ENUM_STARTBOOST_SCOPED_ENUM_END。所以让我们回过头来看看。

据我所知,除了Boost 1.40.0 boost/detail/scoped_enum_emulation.hpp中的头文件本身之外,这些宏首先没有任何文档。它用于Boost.Filesystem的相同目的。

当时,没有copy_option::none值。因此,如果Boost.Config自动定义BOOST_NO_SCOPED_ENUMS,则枚举定义扩展为C ++ 03兼容代码:

struct copy_option { enum enum_t
  { fail_if_exists, overwrite_if_exists };
};

如果未定义BOOST_NO_SCOPED_ENUMS,则相同的定义扩展为C ++ 0x-only代码(这是在C ++ 11正式之前):

enum class copy_option
  { fail_if_exists, overwrite_if_exists };

允许并要求编写例如copy_option::overwrite_if_exists。但有一个问题:在C ++ 03模式下,该值的类型为copy_option::enum_t,但在C ++ 0x模式下,类型只是copy_option。因此,scoped_enum_emulation.hpp标头定义了第三个宏BOOST_SCOPED_ENUM(EnumName),它在C ++ 03模式下扩展为EnumName::enum_t,在C ++ 0x模式下扩展为EnumName。虽然C ++ 03版本仍然存在一些问题,例如隐式转换为整数类型....

要获得在任何一种情况下都能工作的代码,建议在需要变量声明,函数参数或函数返回类型作为范围枚举类型时使用BOOST_SCOPED_ENUM(EnumName)。这仍然有效,因此您可以通过编写

来解决问题
BOOST_SCOPED_ENUM(boost::filesystem::copy_option) myFunc();

但现在也有其他选择可以考虑。

Boost 1.44.0从使用enum_t切换到enum_type。所以这是你的代码最早开始的。

Boost 1.50.0更改了旧宏BOOST_SCOPED_ENUM_STARTBOOST_SCOPED_ENUM_END的定义,不推荐使用它们,并引入了新的宏BOOST_SCOPED_ENUM_DECLARE_BEGINBOOST_SCOPED_ENUM_DECLARE_END。他们还在Boost.Thread下介绍了一些文档,显然也开始使用它。 Boost.Filesystem的copy_option仍然使用旧的宏,但定义了BOOST_NO_SCOPED_ENUMS的C ++ 03扩展变为:

struct copy_option {
    typedef void is_boost_scoped_enum_tag;
    typedef int underlying_type;
    copy_option() {}
    explicit copy_option(underlying_type v) : v_(v) {}
    underlying_type get_underlying_value_() const { return v_; }
private:
    underlying_type v_;
    typedef copy_option self_type;
public:
    enum enum_type
      {none=0, fail_if_exists = none, overwrite_if_exists};
    enum_type get_native_value_() const { return enum_type(v_); }
    operator enum_type() const { return get_native_value_(); }
    friend bool operator ==(self_type lhs, self_type rhs) { return enum_type(lhs.v_)==enum_type(rhs.v_); }
    friend bool operator ==(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)==rhs; }
    friend bool operator ==(enum_type lhs, self_type rhs) { return lhs==enum_type(rhs.v_); }
    friend bool operator !=(self_type lhs, self_type rhs) { return enum_type(lhs.v_)!=enum_type(rhs.v_); }
    friend bool operator !=(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)!=rhs; }
    friend bool operator !=(enum_type lhs, self_type rhs) { return lhs!=enum_type(rhs.v_); }
    friend bool operator <(self_type lhs, self_type rhs) { return enum_type(lhs.v_)<enum_type(rhs.v_); }
    friend bool operator <(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)<rhs; }
    friend bool operator <(enum_type lhs, self_type rhs) { return lhs<enum_type(rhs.v_); }
    friend bool operator <=(self_type lhs, self_type rhs) { return enum_type(lhs.v_)<=enum_type(rhs.v_); }
    friend bool operator <=(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)<=rhs; }
    friend bool operator <=(enum_type lhs, self_type rhs) { return lhs<=enum_type(rhs.v_); }
    friend bool operator >(self_type lhs, self_type rhs) { return enum_type(lhs.v_)>enum_type(rhs.v_); }
    friend bool operator >(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)>rhs; }
    friend bool operator >(enum_type lhs, self_type rhs) { return lhs>enum_type(rhs.v_); }
    friend bool operator >=(self_type lhs, self_type rhs) { return enum_type(lhs.v_)>=enum_type(rhs.v_); }
    friend bool operator >=(self_type lhs, enum_type rhs) { return enum_type(lhs.v_)>=rhs; }
    friend bool operator >=(enum_type lhs, self_type rhs) { return lhs>=enum_type(rhs.v_); }
};

请注意,他们现在已将C ++ 03类型copy_option放入一个主要与其包含的枚举类型兼容的类中。此外,它在某些情况下更像是C ++ 11范围的枚举:例如,如果optcopy_option,则您无法opt==1。所以你可能想考虑做

boost::filesystem::copy_option myFunc();

代替。最大的问题是(因为使用了旧的宏),copy_option的构造函数是显式的,因此必须使用直接初始化而不是复制初始化来从枚举器值获取{{1 }}。也就是说,copy_optioncopy_option var = copy_option::fail_if_exists;无法正常工作,但return copy_option::fail_if_exists;copy_option var(copy_option::fail_if_exists);会有效。

在Boost 1.53.0中,所涉及的Boost.Config宏从return copy_option(copy_option::fail_if_exists);更改为BOOST_NO_SCOPED_ENUMS

在Boost 1.56.0中,scoped enum支持转移到Boost.Core,文件boost / core / scoped_enum.hpp。