Search code examples
c++classzeromqforward-declaration

How to declare a zeromq socket in a cpp class


I am trying to create a generic node using zmq that will form a dynamic computation graph, however I am getting an error in forward declaration of the zmq sockets within my class. I wondered if anyone could shed some light on this? A stripped down version of the class is;

node.hpp

/* 
 *  node.hpp
*/ 

#ifndef NODE_
#define NODE_

#include <iostream>
#include "zmq.hpp"

class Node
{
private:
    std::string name_;
    std::ostream& log_;
    zmq::context_t context_;
    zmq::socket_t subscriber_;
    zmq::socket_t publisher_;

public:
    Node(std::ostream& log, std::string name);
    void sendlog(std::string msg);
};

#endif // NODE_ 

node.cpp

/* 
 *  node.cpp
*/ 

#include <iostream>
#include <string>
#include "zmq.hpp"
#include "node.hpp"

Node::Node(std::ostream& log, std::string name): 
    log_(log),
    name_(name)
{
    sendlog(std::string("initialising ") + name_);

    zmq::context_t context_(1);
    zmq::socket_t subscriber_(context_, zmq::socket_type::sub);
    zmq::socket_t publisher_(context_, zmq::socket_type::pub);

    subscriber_.connect("ipc:///tmp/out.ipc");
    publisher_.connect("ipc:///tmp/in.ipc");

    sendlog(std::string("finished initialisation"));
}

void Node::sendlog(std::string msg)
{
    this->log_ << msg << std::endl;
}

the error I get from g++

g++ main.cpp node.cpp -lzmq

node.cpp: In constructor ‘Node::Node(std::ostream&, std::__cxx11::string)’:
node.cpp:12:15: error: no matching function for call to ‘zmq::socket_t::socket_t()’
     name_(name)

however when I look in zmq.hpp I see

namespace zmq
{
class socket_t : public detail::socket_base
...

I assume I am doing the declaration incorrectly in some way? I am not so well versed in cpp but am using this as a project to get back up to scratch so general comments/literature references are welcome.


Solution

  • There are two issues with the code shown. Firstly with...

    zmq::context_t context_(1);
    zmq::socket_t subscriber_(context_, zmq::socket_type::sub);
    zmq::socket_t publisher_(context_, zmq::socket_type::pub);
    

    you are creating locally scoped variables that shadow the identically named member variables. Secondly because you don't explicitly initialize subscriber_ or publisher_ in the ctor's initializer list the compiler will attempt to use an implicit call to their default constructors. But zmq::socket_t doesn't have a default constructor, hence the error you see.

    The fix is simply to move the initialization of the context_, subscriber_ and publisher_ members into the ctor's initializer list with...

    Node::Node(std::ostream& log, std::string name)
        : log_(log)
        , name_(name)
        , context_(1)
        , subscriber_(context_, zmq::socket_type::sub)
        , publisher_(context_, zmq::socket_type::pub)
    {
        sendlog(std::string("initialising ") + name_);
    
        subscriber_.connect("ipc:///tmp/out.ipc");
        publisher_.connect("ipc:///tmp/in.ipc");
    
        sendlog(std::string("finished initialisation"));
    }