将成员函数添加到Boost.Variant

时间:2010-03-02 08:28:28

标签: c++ boost boost-variant

在我的C ++库中,我有一个类型boost::variant<A,B>和许多算法将此类型作为输入。我没有成员函数,而是拥有此类型的全局函数,例如void f( boost::variant<A,B>& var )。我知道这也可以通过模板实现,但这不适合我的设计。

我对这种编程风格很满意:

boost::variant<A, B> v;
f( v );

但是这个库的一些用户不习惯,并且由于Boost.Variant概念被类型定义隐藏,他们感觉就像调用v.f()

为实现这一目标,我可以想到两种可能性:1)覆盖boost::variant和2)重新实现boost::variant并添加我自己的成员函数。我不确定这些想法是否合适。你能帮我个忙吗?还有其他可能性吗?

2 个答案:

答案 0 :(得分:5)

另一种可能性:使用聚合。然后,您不要直接将boost.variant公开给库的用户,为您提供方式更多的自由,以便将来进行改进,并且可以大大简化一些调试任务。

一般建议: 聚合比继承更紧密耦合,因此默认情况下更好,除了您知道一个用例,您明确希望将对象实例传递给仅使用变体的现有函数。甚至基本类的设计应该考虑到继承。

您的问题汇总示例: 据我了解,免费功能已经存在,并采取变体。只需使用变量的唯一数据成员定义一个类,并提供公共成员函数,这些函数除了使用成员变量调用已存在的自由函数之外什么都不做,比如

class variant_wrapper {
  boost::variant<A,B> m_variant;
public:
  variant_wrapper(...) : m_variant(...) {} // whatever c_tor you need.
  void f() {  f(m_variant); }
};

使用这种方法,你抽象出你正在使用boost.variant进行实现的事实(你已经通过库用户的typedef来做),让你可以自由地改变它(用于优化或功能扩展或者无论如何),您可以决定使值不可变,有一个更简单的方法来调试对算法的访问等等。

聚合的缺点是你不能只是将包装器传递给static_visitor,但由于你的用户不知道有一个变体,并且你知道只是传递成员变量,我看不出一个大问题这里。

最后的咆哮: C ++不是Java。您需要修复库的用户......

您希望拥有的是C#扩展方法; C ++中不存在这样的东西。但是,我会重新实现/实现 - 复制boost.variant(维护负担),而我继承它。尽可能使用聚合。

答案 1 :(得分:2)

我来自boost :: variant。只要您不向类中添加数据成员,并且不添加虚函数,这应该没问题。 (你或许可以做其中的一些事情,但我认为事情会更多一些)。无论如何,这对我来说似乎没问题。

#include "boost/variant.hpp"
#include <iostream>

template<typename T1, typename T2>
struct my_print : public boost::static_visitor<>
{
  void operator()( T1 t1 ) const
  {
    std::cout<<"FIRST TYPE "<<t1<<std::endl;
  }
  void operator()( T2 t2 ) const
  {
    std::cout<<"SECOND TYPE "<<t2<<std::endl;
  }
};

template<typename T1, typename T2>
class MyVariant : public boost::variant<T1,T2>
{
  public:
    void print()
    {
      boost::apply_visitor(my_print<T1,T2>(), *this );
    }

    template<typename T>
    MyVariant<T1,T2>& operator=(const T& t)
    {
      boost::variant<T1,T2>::operator=(t);
      return *this;
    }

    MyVariant(const T1& t) : boost::variant<T1,T2>(t)
    {
    }

    MyVariant(const T2& t) : boost::variant<T1,T2>(t)
    {
    }

    template<typename T>
    explicit MyVariant(const T& t) : boost::variant<T1,T2>(t)
    {
    }
};

int main()
{
  MyVariant<int,std::string> s=1;
  s.print();
  s=std::string("hello");
  s.print();

  MyVariant<int,std::string> v2 = s;
  v2.print();

  s=boost::variant<int,std::string>(3);
  s.print();
}
相关问题