c++explicit-conversionexplicit-constructorclass-constructors

C++ 'no matching function for call to' and 'no known conversion for argument'


I have this piece of code:

    class Enum {
     public:
      const int &value() const {
        return value_;
      }

      bool operator==(const Enum &other) const {
        return (other.value() == this->value_);
      }

      bool operator!=(const Enum &other) const {
        return !(*this == other);
      }

      bool operator<(const Enum& other) const {
        return value_ < other.value();
    }

     protected:
      Enum(const int &value) : value_(value) {
      }

      void set_value(int value) {
        value_ = value;
      }

     private:
      int value_;
    };

    /*
     * Port-Id Base classes
     */
    class PortIdBase : public Enum {
     public:
      virtual ~PortIdBase() {}
     protected:
        PortIdBase(int value) : Enum(value) {}
    };

    class PortId : public PortIdBase {
     public:
      PortId(int value) : PortIdBase(value) {}
      PortId() : PortIdBase(0) {}
      virtual ~PortId() {}
    };

    class GlobalPortId {
    public:
      GlobalPortId(const PortIdBase id_base) : base_(id_base) {}
      virtual ~GlobalPortId() {}

    private:
      PortIdBase base_;
    };


    class CfpDevice {
     public:
      explicit CfpDevice(int dev_cfp_instance) : instance_(dev_cfp_instance) {}
      virtual ~CfpDevice() {}

    private:
      int instance_;
    };

    class Cfp {
    public:
      explicit Cfp(const GlobalPortId &id,
          CfpDevice* const device) : id_(id),
                                     device_(device) {}
      ~Cfp() { delete device_; }

    private:
      const GlobalPortId id_;
      CfpDevice* const device_;
    };

    int main() {
      int number_of_devices = 5;
      for(int i = 0; i < number_of_devices; ++i) {
        GlobalPortId port(PortId(i));
        CfpDevice *cfp_device = new CfpDevice(i);
        Cfp *cfp = new Cfp(port, cfp_device);
      }
      return 0;
    }

I had to change the code to fit all in one file, so don't worry about implementing separately from definitions and memory allocation. I'll fix everything in my original files. My question is why compiling this code I have this message:

test.cc: In function ‘int main()’: test.cc:86:40: error: no matching function for call to ‘Cfp::Cfp(GlobalPortId (&)(PortId), CfpDevice*&)’ Cfp cfp = new Cfp(port, cfp_device); ^ test.cc:86:40: note: candidates are: test.cc:70:12: note: Cfp::Cfp(const GlobalPortId&, CfpDevice) explicit Cfp(const GlobalPortId &id, ^ test.cc:70:12: note: no known conversion for argument 1 from ‘GlobalPortId(PortId)’ to ‘const GlobalPortId&’ test.cc:68:7: note: Cfp::Cfp(const Cfp&) class Cfp { ^ test.cc:68:7: note: candidate expects 1 argument, 2 provided

However if I change:

GlobalPortId port(PortId(i));

for

GlobalPortId port(static_cast<PortIdBase>(PortId(i)));

It works.

Also if I remove

GlobalPortId port(PortId(i));

and instantiates inside Cfp creation:

Cfp *cfp = new Cfp(GlobalPortId(PortId(i)), cfp_device);

It also works.

Is there anybody who could explain:

  1. Why is it allowed to instantiate Cfp, calling GlobalPortId and PortId constructors at the same line? But it isn't allowed to use them when you instantiate them separately.
  2. Why it isn't allowed to instantiate Cfp using 'port' without cast?

Solution

  • You have been hit by the most vexing parse. GlobalPortId port(PortId(i)); declares a function called port that takes a parameter of type PortId named i and returns a GlobalPortId. I believe extra parens will take care of it: GlobalPortId port((PortId(i)));