no viable conversion from 'shared_ptr<src::IdInterface>' to 'shared_ptr<IdInterface>' - c++11

I am trying to understand an error I see when attempting to implement the Visitor pattern for validation purpose. When i execute cmake ../ from the build directory i am getting the following error:
validator/src/Id.cpp:30:38: error: no viable conversion from 'shared_ptr<src::IdInterface>' to 'shared_ptr<IdInterface>'
bool isValid = validator->isValid( castedObj );
/home/tito/Projects/validator/src/IdValidatorInterface.h:24:50: note: passing argument to parameter 'entity' here
virtual bool isValid( shared_ptr<IdInterface> entity ) = 0;
I have been able to replicate the error with simple 3 classes For the sake of the example i have put them in the same namespace.
Those classes are "Id" class this is the element i would like to validate. The Id inherits from BasePrimitive. The sole purpose of BasePrimitive class is to be able to get a share pointer validating entity since the BasePrimitive class inherits from
"enable_shared_from_this". i.e. the code below
#include "Id.h"
#include "IdInterface.h"
#include "IdValidatorInterface.h"
#include <iostream>
using namespace std;
namespace src
{
const string Id::name = "ID";
Id::Id()
{
}
Id::~Id()
{
}
bool Id::validate(shared_ptr<IdValidatorInterface> validator)
{
shared_ptr<Id> thisObj = shared_from_this();
shared_ptr<IdInterface> castedObj = static_pointer_cast<IdInterface>(thisObj);
bool isValid = validator->isValid( castedObj );
if (!isValid)
{
vector<string> vectorOfErrors = validator->validate(castedObj );
std::cout << " the Id has NOT been validated" << std::endl;
} else
{
std::cout << " the Id has been validated" << std::endl;
}
return isValid;
}
string Id::getName() const {
return Id::name;
}
}
the part where the code is broken is this one: Here i get a share_ptr from this class and then do a static pointer case. This works well but when i try to pass it to the isValid method then it breaks.
shared_ptr<Id> thisObj = shared_from_this();
shared_ptr<IdInterface> castedObj = static_pointer_cast<IdInterface>(thisObj);
bool isValid = validator->isValid( castedObj );
and the BasePrimitive class
namespace src {
class BasePrimitive: public enable_shared_from_this<BasePrimitive> {
public:
~BasePrimitive();
BasePrimitive();
};
}
Then i have my validator class i.e. IdValidator
#include "IdValidator.h"
#include "Id.h"
#include "IdInterface.h"
using namespace std;
namespace src
{
using Id = src::Id;
IdValidator::IdValidator()
{
}
bool IdValidator::isValid(shared_ptr<IdInterface> entity)
{
vector<string> listOfErros = validate(entity);
if(listOfErros.empty() ){
return false;
}else{
return true;
}
}
vector<string> IdValidator::validate(shared_ptr<IdInterface> entity)
{
vector<string> stringList = vector<string>();
// do some validation of the name
string name = entity->getName()
if (name == "BadName")
{
string error = "Error. id name is bad";
stringList.push_back(error);
return stringList;
}
return stringList;
}
}
And i do have 3 other interfaces i.e. BaseElementValidatorInterface, IdValidatableInterface, IdValidatorInterface which are there simply for explicit in order to state that those a pure virtual functions.
in the last interface i.e. IdValidatorInterface i am using a forward declare to the IdInterface in order to avoid cyclic includes.
i.e.
class IdInterface;
The first probelm:
"no viable conversion from 'shared_ptr' to 'shared_ptr'"
the only difference here i see is the full qualified namespace. I would like to understand the nature i.e. the origin of this error. Is this something related to the compiled definitions I pass to clang i.e.
add_definitions(" -pedantic -pedantic-errors -W ")
add_definitions(" -Wall -Wextra -Werror -Wshadow -Wnon-virtual-dtor ")
add_definitions(" -v ")
or something else.
I have found multiple articles in stackoverflow about this but all of those were mainly about different types i.e. somethig like bools and string.
like this one
no viable conversion from 'int' to 'Time'
No viable conversion from 'bool' to 'std::string'
I do understand the articles mentioned above, but in my case the compiler is seeing the same type except the namespace is different i.e.'shared_ptr' to 'shared_ptr' how to i tell the compiler that those are the same objects? Why is the compiler seeing different namespaces when this is the same class i.e. "IdInterface". In some of the articles above it has been mentioned that this error can be seen if the class in not defined , but for this reason i use explicetelly the fotrward declaration.
I have put those whole 3 classes and the 3 interfaces on github to show the complete picture. https://github.com/courteous/visitor/tree/master/src
Any help is highly appreciated

Related

Is there any method to pass protobuf object to shared_ptr?

I want to copy protobuf msg "SmConfig" to an shared_ptr like below:
SignalMachine::SignalMachine(SmConfig* sm_config) {
sm_config_ = std::make_shared<SmConfig>();
sm_config_.CopyFrom(*sm_config);
}
class SignalMachine {
private:
std::shared_ptr<SmConfig> sm_config_;
}
Because I need to keep SmConfig(protobuf) in "class SignalMachine", I used the above method, is it reasonable? in fact, I did not find the corresponding description in the official document.
You can use copy constructor:
SignalMachine::SignalMachine(SmConfig* sm_config) {
if (sm_config != nullptr)
sm_config_ = std::make_shared<SmConfig>(*sm_config);
// else error handling
}

How to call a class function which only argument is &

Here's my code:
class Patient {
public:
const int patientId;
const PatientKind kind;
const bool hasInsurance;
std::vector<ProcedureKind> procedures;
Patient(int, PatientKind, bool);
bool addProcedure(const ProcedureKind procedure);
double billing();
virtual double liability() = 0;
};
class Hospital {
public:
Patient &addPatient(const PatientInfo &);
};`
I don't know how to write:
Patient &Hospital::addPatient(const PatientInfo &)
{
}
Whatever I try to return or pass as argument gives me an error... Also, I don't understand what is this function expecting as an argument with just &?
Any kind of help / insight will be appreciated :D
Seems like you're trying to implement a header definition someone else wrote. That & means that the function expects a reference to an instance of PatientInfo. In the implementation, the only thing you have to do is to give the parameter a name like so:
Patient& addPatient(const PatientInfo& info)
{
// do whatever you need with 'info'
}
You can read more about c++ function declaration and implementation in any basic c++ text.

C++, getting name of the plugin from derived class

I have a requirement wherein, I need to create a base class which will have some pure virtual functions which would be implemented by derived classes. These virtual functions are not enough and I also need to get the name of the plugin to be given to a library from the base class which I will create.
I am using factory pattern. Basically thought that based on the plugin name I would create the instance of that particular derived class.
But, the problem here is since I am using factory pattern, until I send plugin name I would not create object and until object is created plugin name would not be known. Because of this I always see empty plugin name.
Many plugins would be derived from this common base class, it's important to know name of the plugin at runtime.
Please suggest
You need to register a factory for each plugin type in your central factory.
struct common_args {
int width; // whatever
};
struct BasePlugin {
virtual ~BasePlugin() {}
virtual std::string get_name() const = 0;
virtual void do_stuff() = 0;
};
using single_type_factory = std::function<std::unique_ptr<BasePlugin>( common_args ) >;
using plugin_factory = std::function<std::unique_ptr<BasePlugin>( std::string name, common_args ) >;
struct central_factory:plugin_factory {
central_factory(central_factory&&)=delete;
central_factory():
plugin_factory(
[this](std::string name, common_args args)
->std::unique_ptr<BasePlugin>
{
auto it = m_factories.find(name);
if (it == m_factories.end())
return {};
return (*it)(args);
}
)
{}
void register_plugin_type( std::string name, single_type_factory f ) {
m_factories[name] = f;
}
private:
std::unordered_map<std::string, single_type_factory> m_factories;
};
that is just a sketch.

Derived class initialization with parameter of another derived class

I am new in Abstract classes so please excuse any ignorant mistakes
The exercise is given from my school, so the main.cpp file is to be used, almost as it is
I am trying to create a simple calculator in Eclipse using C++11
There exists a simple Abstract class with two virtual methods.
The two derived classes are simply the "Result" and the "Const" classes.
This is the header file of the Abstract class called
Expression.h
class Expression
{
public:
Expression();
virtual ~Expression();
//methods
};
Following is the source file of Expression
Expression.cpp
#include "expression.h"
#include <iostream>
Expression::Expression(){}
Expression::~Expression(){}
Then I have created two classes called Const and Result
Const.h
#include <iostream>
#include "expression.h"
class Const : public Expression
{
public:
Const(int value);
//inherited methods
private:
int value;
};
and the source file
Const.cpp
#include "expression.h"
#include "Const.h"
Const::Const(int x)
{
value=x;
};
//inherited methods
Result.h
#include <iostream>
#include "expression.h"
#include "Const.h"
class Result : public Expression
{
public:
Result(Const& c);
//inherited methods
private:
double value;
};
Result.cpp
#include "expression.h"
#include "Result.h"
Result::Result(Const& c)
{
value=c.point;
};
//inherited methods
So what i need is to understand
main.cpp
#include <iostream>
#include "expression.h"
#include "const.h"
#include "result.h"
void testResult()
{
Result res (new Const(4));
//Here an inherited method will be used to print the contents of object res
}
int main()
{
testResult();
return 0;
}
The problem i can't solve is the line
Result res (new Const(4));
The error i get is
Conversion from 'Const* to non-scalar type 'Result' requested
The thing is that what is described in this line should be used as it is, and i can't seem to find exactly what it is.
EDIT
The question as asked firstly was apparently misleading due to my fault, tried to fix the question so as to describe exactly my problem
You started correctly, by creating a common base class for both Const and Result, but then completely ignored it.
All your problems are indeed in this line:
Result res = (new Const(4));
First of all, operator new in C++ returns a pointer, not a reference. Also, this would be a good place to make use of your base class:
Expression* res = new Const(4);
Since you declared methods evaluate() and print() as virtual, the object res is pointing to will be correctly resolved as an instance of Const when you call res->print() or res->evaluate().
This will use Const version of print(). If you want to use the Result version - abstract classes won't help you here, you need to use casting. Create your own operator=(Const &) in Result or operator Result() in Const.
If you had two derived classes DerivedClass1 and DerivedClass2 both derived from some BaseClass then to instantiate a pointer to a DerivedClass1 and use it in polymorphic way use:
BaseClass* p = new DerivedClass1;
To create a base class pointer to a DerivedClass2 use:
BaseClass* p = new DerivedClass2;
And not the:
DerivedClass1* p = new DerivedClass2;
In your example both Result and Const classes are derived from Expression class hence the confusion. To pass in an argument of SomeClass& type, create a temporary object of SomeClass and pass it in:
SomeClass o;
someFunction(o);
One issue is that
double point= value;
doesn't initialize your member, but a new unused local variable.
just do
point = value;
Class Result and Const are two different classes. This means the type conversion
Result *res = (new Const(4));
is not possible. To do what you want, since both classes inherit from Expression, do:
Expression * res = new Result( objConst);
Where objConst is a Const object.

Should this simple structure have an implicit move constructor?

In this test:
#include <string>
struct thing {
std::string name_;
};
class test {
thing id_;
public:
test(thing id) : id_{std::move(id)} {}
};
I would expect struct thing to have an implicit move constructor, so that class test can use std::move() to initialise its data member.
Clang version 3.4.1 gives this error:
error: no viable conversion from 'typename remove_reference<thing&>::type' (aka 'thing') to 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
The problem can be solved by adding a move constructor to struct thing, which of course means that a converting constructor and an explicitly defaulted copy constructor also needs to be added.
I do not understand why I cannot move struct thing around implicitly.
You are using a brace initialization - id_{std::move(id)}. In your case, as though struct thing is a POD (plain old data) it means, that C++ compiler tries to initialize the first member - std::string name_ instead of using a default constructor of struct thing object. Read more about aggregates and PODs.
In this case, because of the braces, class test's constructor is equivalent to something like this:
class test {
thing id_;
public:
test(thing id) {
id_.name_ = std::move(id); // Notice that this causes
// the "no viable conversion" error
}
};
Solution 1: You need to declare explicitly that you want to use a default struct thing's constructor by using parenthesis instead of braces:
#include <string>
struct thing {
std::string name_;
};
class test {
thing id_;
public:
test(thing id) : id_(std::move(id)) {} // Default c-tor will be used
};
Solution 2: You could also declare a user-defined constructor of struct thing to make it non-POD:
#include <string>
struct thing {
std::string name_;
thing(thing&&) {} // Used-defined move constructor
};
class test {
thing id_;
public:
test(thing id) : id_{std::move(id)} {} // You can use braces again
};

Resources