Boost C++ 库

...世界上最受尊敬和专家设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

参考

概念
头文件 <boost/variant.hpp>
头文件 <boost/variant/variant_fwd.hpp>
头文件 <boost/variant/variant.hpp>
头文件 <boost/variant/recursive_variant.hpp>
头文件 <boost/variant/recursive_wrapper.hpp>
头文件 <boost/variant/apply_visitor.hpp>
头文件 <boost/variant/multivisitors.hpp>
头文件 <boost/variant/get.hpp>
头文件 <boost/variant/polymorphic_get.hpp>
头文件 <boost/variant/bad_visit.hpp>
头文件 <boost/variant/static_visitor.hpp>
头文件 <boost/variant/visitor_ptr.hpp>

概念

BoundedType(有界类型)

有界类型的要求如下

  • 可拷贝构造 或 可移动构造。
  • 析构函数支持无异常安全保证。
  • variant 模板实例化时必须是完整的。(参见 boost::recursive_wrapper<T>,它是一个接受不完整类型的类型包装器,用于启用递归 variant 类型。)

指定为 variant 模板参数的每个类型都必须至少满足上述要求。此外,variant 的某些特性只有在其有界类型满足以下附加概念的要求时才可用

  • 可赋值:当且仅当其每个有界类型都满足该概念的要求时,variant 本身才可赋值。(注意,顶级 const 限定类型和引用类型满足这些要求。)
  • 可移动赋值: 当且仅当其每个有界类型都满足该概念的要求时,variant 本身才可移动赋值。(注意,顶级 const 限定类型和引用类型满足这些要求。)
  • 可默认构造 [20.1.4]:当且仅当其第一个有界类型(即 T1)满足该概念的要求时,variant 本身才可默认构造
  • 可相等比较:当且仅当其每个有界类型都满足该概念的要求时,variant 本身才可相等比较
  • 可小于比较:当且仅当其每个有界类型都满足该概念的要求时,variant 本身才可小于比较
  • 可输出流:当且仅当其每个有界类型都满足该概念的要求时,variant 本身才可输出流
  • 可哈希:当且仅当其每个有界类型都满足该概念的要求时,variant 本身才可哈希

StaticVisitor(静态访问者)

对类型 T静态访问者的要求如下

  • 必须通过重载 operator() 允许作为函数调用,并且能够明确地接受任何 T 类型的值。
  • 必须公开内部类型 result_type。兼容 C++14 的编译器可以自动检测 result_type,但如果定义了 result_type,则将继续使用它。(有关将函数用作访问者的解决方案,请参见 boost::visitor_ptr。)
  • 如果 result_type 不是 void,则函数对象的每个操作都必须返回一个可隐式转换为 result_type 的值。
示例

以下类满足多种类型的静态访问者的要求(即,显式:intstd::string;或者,例如,隐式:shortconst char *;等等)

class my_visitor
    : public boost::static_visitor<int>
{
public:

    int operator()(int i)
    {
        return i * 2;
    }

    int operator()(const std::string& s)
    {
        return s.length();
    }

};

另一个示例是以下类,其函数调用运算符是一个成员模板,允许它对多种类型的值进行操作。因此,以下类是任何支持流输出的类型的访问者(例如,intdoublestd::string 等)

class printer
    : public boost::static_visitor<>
{
    template <typename T>
    void operator()(const T& t)
    {
        std::cout << t << std::endl;
    }
};

兼容 C++14 的编译器会自动检测 result_type

    boost::variant<int, float> v;
    // ...

    boost::apply_visitor(
        [](auto val) { return std::to_string(val); },
        v
    );

OutputStreamable(可输出流)

可输出流类型 T 的要求如下

  • 对于任何 T 类型的对象 tstd::cout << t 必须是有效的表达式。

Hashable(可哈希)

可哈希类型 T 的要求如下

  • 对于任何 T 类型的对象 tboost::hash<T>()(t) 必须是有效的表达式。

头文件 <boost/variant.hpp>

此头文件只是为了方便用户而存在,它包含 boost/variant 目录中的所有头文件,但 <boost/multivisiors.hpp> 除外。

提供 boost::variantboost::make_variant_overboost::make_recursive_variantboost::make_recursive_variant_over 类模板以及 boost::recursive_variant_ 标记类型的前向声明。还定义了几个预处理器符号,如下所述。

BOOST_VARIANT_ENUM_PARAMS(param)
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(param)
BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH
BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
namespace boost {
  template<typename T1, typename T2 = unspecified, ..., 
           typename TN = unspecified> 
    class variant;

  template<typename Sequence> class make_variant_over;
  template<typename T1, typename T2, ..., typename TN> 
    void swap(variant<T1, T2, ..., TN> &, variant<T1, T2, ..., TN> &);
  template<typename ElemType, typename Traits, typename T1, typename T2, ..., 
           typename TN> 
    std::basic_ostream<ElemType,Traits> & 
    operator<<(std::basic_ostream<ElemType,Traits> &, 
               const variant<T1, T2, ..., TN> &);
  template<typename T1, typename T2, ..., typename TN> 
    std::size_t hash_value(const variant<T1, T2, ..., TN> &);
}
namespace boost {
  typedef unspecified recursive_variant_;

  template<typename T1, typename T2 = unspecified, ..., 
           typename TN = unspecified> 
    class make_recursive_variant;
  template<typename Sequence> class make_recursive_variant_over;
}
namespace boost {
  template<typename T> class recursive_wrapper;
  template<typename T> class is_recursive_wrapper;
  template<typename T> class unwrap_recursive_wrapper;
}
namespace boost {
  template<typename Visitor> class apply_visitor_delayed_t;
  template<typename Visitor> class apply_visitor_delayed_cpp14_t;
  template<typename Visitor, typename Variant> 
    typename Visitor::result_type apply_visitor(Visitor &, Variant&&);
  template<typename Visitor, typename Variant> 
    typename Visitor::result_type apply_visitor(const Visitor &, Variant&&);
  template<typename BinaryVisitor, typename Variant1, typename Variant2> 
    typename BinaryVisitor::result_type OR decltype(auto) 
    apply_visitor(BinaryVisitor &, Variant1&&, Variant2&&);
  template<typename BinaryVisitor, typename Variant1, typename Variant2> 
    typename BinaryVisitor::result_type OR decltype(auto) 
    apply_visitor(const BinaryVisitor &, Variant1&&, Variant2&&);
  template<typename MultiVisitor, typename Variant1, typename Variant2, 
           typename Variant3> 
    typename MultiVisitor::result_type OR decltype(auto) 
    apply_visitor(MultiVisitor &, Variant1&&, Variant2&&, Variant3&&, ...);
  template<typename MultiVisitor, typename Variant1, typename Variant2, 
           typename Variant3> 
    typename MultiVisitor::result_type OR decltype(auto) 
    apply_visitor(const MultiVisitor &, Variant1&&, Variant2&&, Variant3&&, 
                  ...);
  template<typename Visitor> 
    apply_visitor_delayed_t<Visitor> apply_visitor(Visitor &);
  template<typename Visitor> 
    apply_visitor_delayed_cpp14_t<Visitor> apply_visitor(Visitor &);
}

提供针对三个或更多 variant 参数的 apply_visitor 的声明。

namespace boost {
  template<typename MultiVisitor, typename Variant1, typename Variant2, 
           typename Variant3> 
    typename MultiVisitor::result_type OR decltype(auto) 
    apply_visitor /*three or more variant parameters*/(MultiVisitor &, 
                                                       Variant1&&, 
                                                       Variant2&&, 
                                                       Variant3&&, ...);
  template<typename MultiVisitor, typename Variant1, typename Variant2, 
           typename Variant3> 
    typename MultiVisitor::result_type OR decltype(auto) 
    apply_visitor /*three or more variant parameters*/(const MultiVisitor &, 
                                                       Variant1&&, 
                                                       Variant2&&, 
                                                       Variant3&&, ...);
}
namespace boost {
  class bad_get;
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U * relaxed_get(variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U * relaxed_get(const variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U & relaxed_get(variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U & relaxed_get(const variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U && relaxed_get(variant<T1, T2, ..., TN> &&);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U * strict_get(variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U * strict_get(const variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U & strict_get(variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U & strict_get(const variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U && strict_get(variant<T1, T2, ..., TN> &&);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U * get(variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U * get(const variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U & get(variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U & get(const variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U && get(variant<T1, T2, ..., TN> &&);
}
namespace boost {
  class bad_polymorphic_get;
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U * polymorphic_relaxed_get(variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U * polymorphic_relaxed_get(const variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U & polymorphic_relaxed_get(variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U & polymorphic_relaxed_get(const variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U * polymorphic_strict_get(variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U * polymorphic_strict_get(const variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U & polymorphic_strict_get(variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U & polymorphic_strict_get(const variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U * polymorphic_get(variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U * polymorphic_get(const variant<T1, T2, ..., TN> *);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    U & polymorphic_get(variant<T1, T2, ..., TN> &);
  template<typename U, typename T1, typename T2, ..., typename TN> 
    const U & polymorphic_get(const variant<T1, T2, ..., TN> &);
}
namespace boost {
  class bad_visit;
}
namespace boost {
  template<typename ResultType> class static_visitor;
}
namespace boost {
  template<typename T, typename R> class visitor_ptr_t;
  template<typename R, typename T> visitor_ptr_t<T,R> visitor_ptr(R (*)(T));
}

PrevUpHomeNext