Can someone let me know what I am doing wrong? I am making the object in my main and trying to pass a string variable to its setter. I keep getting the same error "No viable conversion"
#define PatientType_hpp
#include "PersonType.hpp"
#include "DoctorType.hpp"
#include "dataType.hpp"
class PatientType : public PersonType
{
private:
DoctorType drName;
public:
DoctorType getDrName() const;
void setDrName(DoctorType);
};
#endif /* PatientType_hpp */
//setters and getters
DoctorType PatientType::getDrName() const {
return drName;
}
void PatientType::setDrName(DoctorType drName) {
this->drName = drName;
}
#ifndef DoctorType_hpp
#define DoctorType_hpp
#include "PersonType.hpp"
#include <stdio.h>
class DoctorType: public PersonType
{
private:
string drSpecialty;
public:
string getDrSpecialty()const;
void setDRSpecialty(string);
};
#endif /* DoctorType_hpp */
#include "DoctorType.hpp"
#include <iostream>
string DoctorType::getDrSpecialty()const
{
return drSpecialty;
}
void DoctorType::setDRSpecialty(string drSpecialty)
{
this->drSpecialty=drSpecialty;
}
int main(int argc, const char *argv[]) {
PatientType example;
string drName = "Mr.Scott";
example.setDrName(drName);
// ERROR No viable conversion from 'std::__1::string aka 'basic_string<char, char_traits<char>, allocator<char> >') to 'DoctorType'
}
I'm expecting for it to compile because I am passing in a string into the Patient type which i think accepts strings.
The problem lies here:
void PatientType::setDrName(DoctorType drName)
Here, you expect to send a DoctorType parameter. However, in calling you use:
example.setDrName(drName); where drName is a string, not a DoctorType parameter.
The fix is obvious: either modify the prototype so as it accepts a string parameter or, in calling the method, give it a DoctorType parameter.
The issue is this function:
void PatientType::setDrName(DoctorType drName) {
Here, this function expects parameter of type DoctorType but you are passing std::string.
example.setDrName(drName); // drName is std::string. So, Type mismatch
There are numerous ways to solve this:
Option 1: Change the function signature to void PatientType::setDrName(const std::string &drName) {
Option 2: Less trivial but it works. Define a parameterised constructor in DoctorType accepting std::string as parameter.
Like this:
DoctorType::DoctorType(const std::string &name): name(name) { }
I think Option 2 is suitable in your scenario.
As rightly suggested by #t.niese, you must explicitly create the object of DoctorType and define constructor as explicit. Like this:
explicit DoctorType::DoctorType(const std::string &name): name(name) { }
and while calling it:
example.setDrName(DoctorType(drName));
Related
initial question
While testing with googletest, I use a mocked class, which contains an overloaded method, where one of the arguments differs in type.
This leads to an ambiguous function call when I do
EXPECT_CALL(mockedClass,mockedMethod(_,_)).WillOnce(Return(true));
I tried to combine the internal::AnythingMatcher underscore with a type specification by replacing the argument in question with An<type>(), TypedEq<type>(_), or Matcher<type>(_) as well as writing something like:
Matcher<type> customAnythingMatcher = _;
EXPECT_CALL(mockedClass,mockedMethod(_,customAnythingMatcher)).WillOnce(Return(true));
all to no avail.
Any hints how to disambiguate that call?
update #1
As requested, I elaborate by providing a minimal working -- or in this case a non-working -- example what I am trying to achieve:
myInterfaceToMock.h
#ifndef MYINTERFACETOMOCK_H
#define MYINTERFACETOMOCK_H
#include <QVariant>
#include <QtGlobal>
class MyInterfaceToMock {
virtual bool myMethod(QVariant &firstArgument,
const quint8 secondArgument) const = 0;
virtual bool myMethod(QByteArray &firstArgument,
const quint16 secondArgument) const = 0;
virtual bool myOtherMethod(quint8 firstAndOnlyArgument) const = 0;
};
#endif // MYINTERFACETOMOCK_H
myMock.h
#ifndef MYMOCK_H
#define MYMOCK_H
#include <gmock/gmock.h>
#include <QtCore/QObject>
#include "myInterfaceToMock.h"
class MyMock : public MyInterfaceToMock {
public:
// virtual bool myMethod(QVariant &firstArgument, const quint8 secondArgument)
// const = 0;
MOCK_METHOD(bool, myMethod, (QVariant &, const quint8), (const, override));
// virtual bool myMethod(QByteArray &firstArgument, const quint16
// secondArgument) const = 0;
MOCK_METHOD(bool, myMethod, (QByteArray &, const quint16), (const, override));
// virtual bool myOtherMethod(quint8 firstAndOnlyArgument) const = 0;
MOCK_METHOD(bool, myOtherMethod, (quint8), (const, override));
};
#endif // MYMOCK_H
main.cpp
#include <gmock/gmock-matchers.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <QCoreApplication>
#include <QTimer>
class Tester : public QObject {
Q_OBJECT
public:
Tester(QObject *parent = nullptr) : QObject(parent) {}
public slots:
void run() {
::testing::InitGoogleTest();
emit(result(RUN_ALL_TESTS()));
}
signals:
void result(int res);
};
#include "main.moc"
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
::testing::InitGoogleMock(&argc, argv);
Tester *tester = new Tester(&app);
QObject::connect(tester, &Tester::result, &app, &QCoreApplication::exit);
QTimer::singleShot(0, tester, SLOT(run()));
return app.exec();
}
#include "myMock.h"
TEST(myTest, testMockOverload) {
using namespace testing;
MyMock mock;
// Reference method, which does work all the time
EXPECT_CALL(mock, myOtherMethod(_)).WillRepeatedly(Return(false));
// Using a defined value as argument
QVariant myVariant;
EXPECT_CALL(mock, myMethod(myVariant, 3)).WillOnce(Return(true));
bool result = mock.myMethod(myVariant, 3);
ASSERT_TRUE(result);
// Anything matcher for the unambiguous argument
EXPECT_CALL(mock, myMethod(myVariant, _)).WillOnce(Return(true));
result = mock.myMethod(myVariant, 3);
ASSERT_TRUE(result);
// Trying to match any passed qvariant
EXPECT_CALL(mock, myMethod(An<QVariant>(), _)).WillOnce(Return(true));
}
The compiler error is issued for the last line:
..\googlemock_disambiguate\main.cpp(55): error C2664: 'testing::internal::MockSpec<bool (QByteArray &,quint16)> MyMock::gmock_myMethod(const testing::internal::WithoutMatchers &,const testing::internal::Function<bool (QByteArray &,quint16)> *) const': cannot convert argument 1 from 'testing::Matcher<QVariant>' to 'const testing::Matcher<QVariant &> &'
..\googlemock_disambiguate\main.cpp(55): note: Reason: cannot convert from 'testing::Matcher<QVariant>' to 'const testing::Matcher<QVariant &>'
..\googlemock_disambiguate\main.cpp(55): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
I have a guess that it might have sth. to do with the constness of the method, but I still do not understand the meaning of that error...
Using An<type> is the correct solution.
EXPECT_CALL(mockedClass,mockedMethod(_, An<type>())).WillOnce(Return(true));
If it doesn't work for you, the problem lies elsewhere. Perhaps you can elaborate?
Answering the question myself:
I simply did not specify the type correctly, since I expect a reference to get passed. I always tried to use something like An<type>(), where I should have used An<type&>() instead.
So, based on my above example, the correct line simply is:
EXPECT_CALL(mock, myMethod(An<QVariant&>(), _)).WillOnce(Return(true));
header file:
#include<vector>
#ifndef FOO_H
#define FOO_H
class Foo
{
public:
Foo(int s) : pegs (s, *TOKEN_EMPTY){}
static char const TOKEN_EMPTY=' ';
protected:
std::vector<char*> pegs;
}
When trying to build I get the error:
error: invalid type argument of unary ‘*’ (have ‘char’)
20 | Foo(int s) : pegs (s, *TOKEN_EMPTY){}
In case it isn't clear, I just want to initialize a C++ vector of pointers that point to a static char const variable.
I'm still checking StackOverflow and online, but I am hopeful someone can help me or lead me in the right direction!
Adding few more points in the answer provided by #Roger.
*TOKEN_EMPTY is incorrect syntax, what you need is address of TOKEN_EMPTY so you need to apply & operator to get address of the variable.
the TOKEN_EMPTY is const char string, so when you apply & operator, it would return const char*. So you need to update your vector to hold const char *.
Alternatively you can also use typecast operation to convert const char * to char * but it could possibly lead to issues where you can potentially modify the value of const char.
Here is a sample code.
#include <iostream>
#include <vector>
class Foo
{
public:
Foo(int s) : pegs (s, &TOKEN_EMPTY){}
static char const TOKEN_EMPTY=' ';
protected:
std::vector<const char*> pegs;
};
int main() {
// ues class Foo
return 0;
}
Changed to &TOKEN_EMPTY and had to use:
std::vector<const char*> pegs;
I am working on a Particle project and coming from JS so I'm challenged by callbacks in C++. I am trying to refactor my Firebase code into a reusable class and for this I need callbacks:
void setup() {
firebase = new Firebase;
Serial.begin(9600);
firebase->subscribe();
firebase->setCallback(readCallback);
}
void readCallback(JsonObject& root)
{
r = root["r"];
g = root["g"];
b = root["b"];
Serial.printlnf("Yes! r=%d g=%d b=%d d=%d", r, g, b);
}
Firebase.h:
#ifndef Firebase_h
#define Firebase_h
#include <SparkJson.h>
class Firebase {
public:
Firebase();
void
subscribe(),
setCallback(void (*readCallback)(JsonObject& root));
private:
static void getDataHandler(const char *topic, const char *data);
void (*_readCallback)(JsonObject& root);
};
#endif
Firebase.m:
#include "Particle.h"
// This #include statement was automatically added by the Particle IDE.
#include <SparkJson.h>
#include "ArduinoJson.h"
#include "Firebase.h"
Firebase::Firebase(void) {
Serial.printlnf("Firebase instance created");
}
void Firebase::getDataHandler(const char *topic, const char *data) {
Serial.printlnf("getDataHandler invoked");
StaticJsonBuffer<256> jsonBuffer;
char *mutableCopy = strdup(data);
JsonObject& root = jsonBuffer.parseObject(mutableCopy);
free(mutableCopy);
Serial.printlnf("data received: %s", data);
// _readCallback(root);
}
void Firebase::subscribe() {
Serial.printlnf("Firebase subscribe");
Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);
}
void Firebase::setCallback(void (*readCallback)(JsonObject& root))
{
Serial.printlnf("set callback");
_readCallback = readCallback;
}
When getDataHandler is static everything seems to work but naturally I am having trouble accessing the callback and I get:
invalid use of member 'Firebase::_readCallback' in static member
function
When it's not static I get for this line:
Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);
the following error:
invalid use of non-static member function
When I try to bind it as advised here:
Particle.subscribe("hook-response/test3rdata", std::bind(&Firebase::getDataHandler,this), MY_DEVICES);
I get a mistype as Particle.subscribe does not expect a binded method:
no matching function for call to 'CloudClass::subscribe(const char
[25], std::_Bind_helper::type, Spark_Subscription_Scope_TypeDef)'
Is there a way around it?
You are getting this error because std::bind returns a function object that adheres to the signature void() and not void(char const*, char const*). The reason being, that you didn't specify any placeholders for those arguments. So a quick fix would be:
std::bind(&Firebase::getDataHandler, this, std::placeholders::_1, std::placeholders::_2)
Now the bind helper expects two parameters which it will forward to the bound member function.
Having said all that, there is no reason to use std::bind if a lambda will suffice. Lambdas are in fact superior in most regards. In C++14 there's virtually no reason to use std::bind at all. And even in C++11, your use case can be dealt with by a simple lambda:
Particle.subscribe("hook-response/test3rdata", [this](char const* a, char const* b) { getDataHandler(a, b); }, MY_DEVICES);
I have a class which implements a getter to an std::vector. Derived classes are allowed to change the content of the vector, while any other class may read it (or make a copy in my case), but not change it.
SSCCE with Visual Studio 2010 (but should compile with any other as well).
So in the base class I implemented the getter like this:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
class X
{
public:
inline std::vector<std::string> const &getChilds(void) const
{
return mChilds;
}
void mutateInternal(void)
{
mState != mState;
}
protected:
inline std::vector<std::string> &getChilds(void)
{
return mChilds;
}
private:
std::vector<std::string> mChilds;
bool mState;
};
// Now in the derived class
class Y : public X
{
public:
Y(void)
{
std::vector<std::string> &childs = getChilds();
childs.push_back("Test");
}
};
// In the non derived class:
class Z
{
public:
void myfunction(void)
{
Y y;
std::vector<std::string> s = y.getChilds();
if(s.size() == 0)
y.mutateInternal();
}
};
int main(int argc, char *argv[])
{
return 0;
}
But I get the error
1>junk.cpp(49): error C2248: "X::getChilds": cannot access private member declared in class.
1> junk.cpp(18): Siehe Deklaration von 'X::getChilds'
1> junk.cpp(10): Siehe Deklaration von 'X'
and I don't really see what is wrong with that and why the compiler doesn't take the public version which is const and instead insists on the non-const.
Even if I change the variable to const &s (which wouldn't help in this case) I still get the same error.
Update:
Edited the SSCCE for calling const and non const functions.
In this case it should be
const Y y;
in Z::my_function for call const version of function.
Live
Or just cast to const Y, like
std::vector<std::string> s = const_cast<const Y&>(y).getChilds();
Your case don't work, since access check will be applied only after overload resolution, in call y.getChilds() non-const overload will be picked, since it has the best match.
I am trying to implement the a map from the C++ STL as follows:
#include <string>
#include <iostream>
#include <map>
using namespace std;
#include "assembler.h"
// This Class makes use of the Map Template from the Standart Template Library
// All addresses are stored as numerical (Dec) integers
SymbolTable::SymbolTable() { // Constructor
map <string, int> symbolTable;
int address = 0;
}
void SymbolTable::addEntry(string symbol, int address) {
symbolTable[symbol] = address;
address++;
}
// Returns true if symbolTable already contains symbol
bool SymbolTable::contains(string symbol) {
if (symbolTable.find(symbol) == symbolTable.end()) { return true; }
else { return false; }
}
int SymbolTable::getAddress(string symbol) {
return symbolTable[symbol];
}
I try to compile this with
c++ *.cpp -0 assembler.out
and I get the following error message:
symboltable.cpp:57:9: error: no viable conversion from 'mapped_type' (aka 'std::basic_string<char>') to 'int'
return symbolTable[symbol];
^~~~~~~~~~~~~~~~~~~
1 error generated.
I have searched for this error online and all I get is bug reports relating to the STL and I cannot figure out if those reports are the same problem I am having and if so how to get around it. Am I doing something wrong?
I have tried (probably stupidly) to typecast the offending line as
return (int) symbolTable[symbol];
Thank you for any help.
My header file declares the class as:
class SymbolTable {
public:
SymbolTable();
void addEntry(string, int);
bool contains(string);
int getAddress(string);
private:
map <string, string> symbolTable;
int address;
};
This:
SymbolTable::SymbolTable() { // Constructor
map <string, int> symbolTable;
^
^
is a function-local variable, not a member variable. It is not the same as the symbolTable that you're accessing in e.g. getAddress, which presumably is a member variable. You haven't shown the class body, but my guess is that it's defined differently.