Home > front end >  std::unique_ptr saving reference in a Factory class?
std::unique_ptr saving reference in a Factory class?

Time:01-31

I am attempting to utilize a ConnectionPoolFactory (let's call it Factory A) this factory creates a std::unique_ptr<cpool::ConnectionPool> .. i understand this unique pointer cannot be copied (otherwise it won't stay unique)..

but how can I pass this reference to another factory (let's call it Factory B) for use?

The error that occurs on compilation

thrift_server.cpp: In constructor ‘thriftserverHandlerFactory::thriftserverHandlerFactory(const char*, int, const std::unique_ptr<cpool::ConnectionPool>&)’:
thrift_server.cpp:237:27: error: cannot convert ‘const std::unique_ptr<cpool::ConnectionPool>’ to ‘cpool::ConnectionPool*’ in assignment
  237 |       this->tma_conn_pool=conn_pool;
      |                           ^~~~~~~~~
      |                           |
      |                           const std::unique_ptr<cpool::ConnectionPool>

Factory B - this is an Apache Thrift Server Handler factory... as clients connect to this thrift server.. they should share the same connection pool and if all connections are busy.. we will either pause or timeout new connections

class thriftserverHandlerFactory : public thriftserverIfFactory {
  public:
    ibrokersHandlerFactory(const char* target_thriftserver_host, int target_thriftserver_port, const std::unique_ptr<cpool::ConnectionPool> & conn_pool) {
      this->handler_num=0;
      this->tma_conn_pool=conn_pool;
    }

...

  private:
      unsigned int handler_num;
      cpool::ConnectionPool* tma_conn_pool;
};

Factory A

template <>
class cpool::ConnectionPoolFactory<TMAConnection> {

public:
    static std::unique_ptr<cpool::ConnectionPool> create( const std::uint16_t num_connections ) {
        std::vector< std::unique_ptr<cpool::Connection> > connections;
        for ( std::uint16_t k = 0; k < num_connections;   k ) {
            // cannot use std::make_unique, because constructor is hidden
            connections.emplace_back( std::unique_ptr<TMAConnection>( new TMAConnection{} ) );
        }
        return std::unique_ptr<cpool::ConnectionPool>( new cpool::ConnectionPool{std::move( connections )} );
    }
};

CodePudding user response:

The smart pointer sharing issue is something you are already aware of, so focusing on the how to pass and assign a reference question.

What's wrong

Reference variables (const declared ones aswell) can be assigned only once during initialization. This is what the compiler would complain about if the types would match.

How to fix

Standard variables can be instantiated and assigned at once like this

int a = 0;
int& b = a;

For classes/structs it's working slightly different. Instead of assignment in the constructor body, do this in the initializer list after :

class a {
int& ref;
a (int& b)
: ref{b} {}
};

In your example this would look like this:

class thriftserverHandlerFactory : public thriftserverIfFactory {
  public:
    ibrokersHandlerFactory(const char* target_thriftserver_host, int target_thriftserver_port, const cpool::ConnectionPool& conn_pool) 
    : handler_num{0}, 
    tma_conn_pool {conn_pool}
    {}
  private:
      unsigned int handler_num;
      const cpool::ConnectionPool& tma_conn_pool;
};

I was not sure about the exact type you want to have, since constructor and member did not match (guess because of experimenting), so used cpool::ConnectionPool&in my example. You might want to modify tma_conn_pool to a type that matches (e.g. cpool::ConnectionPool&, or a smart pointer of choice).

This is anyway a good practice to initialize all members like this, because that way you avoid creating members with default values and assign in body.

  •  Tags:  
  • Related