0

note: I am still new to c++, and while this may be a simple issue, yet I am unable to find a solution.

Purpose:

I would like to pass an empty string (as one would in java/C#) to my constructor. I receive an error:

error: no matching function for call to 'ReturnObject::ReturnObject(ResultCode::ClientCode, const char [1])'
         return new ReturnObject(ResultCode::ClientCode::enum_FailedOpeningClientSocket, "");

The ReturnObject's purpose is to encapsulate an enum and a string.

What does this error mean and how can I solve it?

I have attempted changing my constructor parameter from QString data to char data and calling with '' but that resulted in an error empty character constant.

calling code:

return new ReturnObject(ResultCode::ClientCode::enum_FailedSocketConnection, "");

header:

class ReturnObject
{
public:
    ReturnObject(ResultCode enum_code, QString data);

    QString getData();
    ResultCode getCode();

private:
    ResultCode e_code;
    QString data_string;

};

implementation

#include "returnobject.h"

ReturnObject::ReturnObject(){
    data_string="WARN";
}

ReturnObject::ReturnObject(ResultCode enum_code, QString data)
    : e_code(enum_code)
    , data_string(data)
{}

ResultCode ReturnObject::getCode()
{
    return e_code;
}

QString ReturnObject::getData()
{
    return data_string;
}

Thanks to wasthishelpful and a few comments, I made a tragic logic error which had me looking at the wrong parameter, the solution is that I should casting my enum class ResultCode which is the parent class to one of the nested classes, in this case ClientCode, as seen below from my enum class header

enum.h

#ifndef ENUMS_H
#define ENUMS_H

class ResultCode{
public:
    enum class LoginDialogCode{
        enum_LoginSuccess=0,
        enum_InternetOffline=1,
        enum_ServerOffline=2,
        enum_InvalidLoginPass=3,
        enum_EmptyLoginPass=4,
        enum_FailedRetreivingServerList=5,
        enum_TokenFailed=6
    };

    enum class ClientCode{
        enum_SentSuccess=10,
        enum_FailedOpeningClientSocket=11,
        enum_FailedClientSocketConnection=12,
        enum_FailedWritingtoClientSocket=13,
        enum_FailedReadingfromClientSocket=14
    };

    enum class ServerCode{
        enum_ReceivedSuccess=20,
        enum_FailedOpeningListenSocket=21,
        enum_FailedBindingtoListenSocket=22,
        enum_FailedAcceptingListenSocket=23,
        enum_FailedWritingtoListenSocket=24,
        enum_FailedReadingfromListenSocket=25
    };
};

#endif // ENUMS_H
5
  • What is the type of ResultCode::ClientCode::enum_FailedSocketConnection? Commented Oct 12, 2016 at 14:20
  • 4
    You expect a ResultCode but you pass a ClientCode. Commented Oct 12, 2016 at 14:21
  • 2
    There is no constructor that takes a ResultCode::ClientCode parameter, but you've been so sure that the second parameter is the problem that you've ignored the first. Commented Oct 12, 2016 at 14:23
  • @GillBates How foolish of me, thanks for pointing that out Commented Oct 12, 2016 at 14:29
  • @molbdnilo thank you, I did not see that! Commented Oct 12, 2016 at 14:29

1 Answer 1

2

Your error is not on the second, but on the first parameter. From your question, I guess you have code like this:

struct ReturnCode
{
    enum class ClientCode
    {
        enum_FailedSocketConnection,
        // other values
    };
};

So you ended up with two declared types: ReturnCode and ReturnCode::ClientCode. Looking at your constructor declaration:

`ReturnObject::ReturnObject(ResultCode enum_code, QString data)`

It needs an object of type ReturnCode as first parameter, while looking at your call:

ReturnObject(ResultCode::ClientCode::enum_FailedSocketConnection, "")

You pass an object of type ReturnCode::ClientCode as first parameter.

You may change your code like this:

class ReturnObject
{
public:
    ReturnObject(ResultCode::ClientCode enum_code, QString data);

    QString getData();
    ResultCode::ClientCode getCode();

private:
    ResultCode::ClientCode e_code;
    QString data_string;

};

Once you are here. You may consider taking the enumeration out of ResultCode:

enum class ClientCode
{
    enum_FailedSocketConnection,
    // other values
};

class ReturnObject
{
public:
    ReturnObject(ClientCode enum_code, QString data);

    QString getData();
    ClientCode getCode();

private:
    ClientCode e_code;
    QString data_string;

};

This follows the Zen of Python: "Flat is better than nested". IMHO this is also true in C++.

EDIT:

From your comments, we're here on an XY problem, and your code needs to be redesign. Here is a first proposition:

#include <type_traits>

enum class ClientCode{
    // ...
    enum_FailedClientSocketConnection=12,
    // ...
};

template<typename T>
struct ReturnObject
{
    static_assert(std::is_enum<T>::value, "T should be an enum");

    const T e_code;
    const QString data_string;
};

template<typename T>
ReturnObject<T> make_return_object(T e_code, std::string data_string)
{
    return ReturnObject<T>{e_code, data_string};
}

// usage

return make_return_object(
    ClientCode::enum_FailedClientSocketConnection, ""
);

I removed the accessors getData and getCode for public const members: they are just read, and should not change for a given return object, so let them be public, with the const qualifier to prevent modification.

I used templates to represent the code, with static_assert to check the given type is an enumeration.

The drawbacks are:

  • You can pass any enumeration, not only your result codes.
  • make_return_object will return a different type for each different enumeration.
Sign up to request clarification or add additional context in comments.

6 Comments

Hell yeah ! Thanks. One question though, you are almost correct with your derived code, see my update, I have a nested enum. I need cast my ResultCode::enum_FailedOpeningClientSocket as a ResultCode::ClientCode object. How should this be done, rather which should I use, dynamic or static?
Neither dynamic_cast nor static_cast: a nested type is not related to its "nesting" type and there can not be cast between them, as you could have when using inheritance. The nesting type acts here like a namespace with private and protected options. Why do you need ResultCode? Unless you want to pass any enum nested in ResultCodeas argument to your functions, but I can't see the point here: if you need a ClientCode, you should not allow to pass anything else, and the way to do that is to declare the argument as a ClientCode
infact that is exactly why I need ResultCode, since I will using this ReturnObject in a few different classes, I require a class that I can insert any enum from ResultCode and a supporting string/(char array). I just realized I do not require ResultCode as a enum but as a struct as you pointed out. But since I can insert any enum from ResultCode, I am required to typecast it do the appropriate enum class. That is what I am refering to, should this be a normal cast like (ResultCode::ClientCode)ResultCode::ClientCode::enum_Failed.... I am testing this now...
That should NOT be a cast :) You are here in a wrong design. I will propose you an answer, but I can't today
Thank you for the trouble, I have resorted to combining all enums into one class, for the moment. I eagerly await your proposed solution/new design, I would love to get a fresh opinion on this!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.