可以用Pimpl包装boost插座吗?

时间:2009-10-28 03:08:02

标签: c++ boost boost-asio pimpl-idiom

在我们想要以某种方式包装Boost Asio套接字的项目中,using类或包装.h不必包含boost头。

我们通常对包装类使用指针和前向声明。

Foward声明:

namespace boost
{
  namespace asio
  {
    namespace ip
    {
      class udp;
    }
  }
}

然后声明套接字:

  scoped_ptr<boost::asio::ip::udp::socket> socket_;
  scoped_ptr<boost::asio::ip::udp::endpoint> receiveEp_;

(如果您不知道scoped_ptr,请忽略它,问题与标准*指针相同。)

但这会产生编译错误:

error C2027: use of undefined type 'boost::asio::ip::udp'

我理解这是因为udp实际上不是命名空间,而是一个类本身。我们只想使用内部类,任何想法?

2 个答案:

答案 0 :(得分:3)

如果您正在使用pimpl,为什么要将成员变量放在标题中?套接字和端点类型是否在您的界面中使用?如果它们不是你的界面的一部分,那么pimpl习语的重点在于你没有在头文件中定义一个类的成员变量;它们是实施细节。

我希望在头文件中有这样的东西:

// ...

class MyClass {
public:
    MyClass();
    // .. Other member functions

private:
    struct Imp;
    boost::shared_ptr<Imp> m_imp;   // This is the only member variable.
};

然后在您的实施文件中:

#include <boost/asio/whatever.hpp>

struct MyClass::Imp
{
    scoped_ptr<boost::asio::ip::udp::socket> socket_;
    scoped_ptr<boost::asio::ip::udp::endpoint> receiveEp_;

    // Remainder of implementation class ...
};

// Other implementation details.

要回答您的具体问题,您尝试使用的类型是asio udp类中的typedef,因此编译器需要看到该类的定义才能使用它。

答案 1 :(得分:2)

对于内部类型,您唯一的选择是包装所有内容。在前向声明的类中隐藏作用域指针。用户只会看到你的API并传递你自己的对象而不是boost对象。

在您的示例中虽然scoped_ptr看起来像私有成员声明,​​但您可以通过简单的方式逃脱:

// header
class SomeClass 
{ 
public:
    SomeClass();
    // stuff   
private: 
    scoped_ptr<class pimpl_bla> _m; 
};

// source
class pimpl_bla
{
public: 
    scoped_ptr<boost::asio::ip::udp::socket> socket_;
};

SomeClass::SomeClass() 
    :_m(new pimpl_bla)
{ 
}