std::string Constructed in Arguments - c++

I've run into a very tricky C++ compiler error.
When I construct a string to use as an argument, it works when calling a regular method. E.g. printThisString(string(charPtr));
It does not work when constructing an object, if the argument to the constructor is a char*. For example, MyObject a(string(argv[0])); It still does work if the argument is a literal. For example, MyObject b(string("hi"));
#include <iostream>
#include <string>
using namespace std;
void printString(string toPrint) {
cout << toPrint << endl;
}
class MyObject {
int blah;
public:
void aMethod() {}
MyObject (string myStr) {
cout << myStr << endl;
}
};
int main(int argc, char ** argv) {
string s1(argv[0]);
char * s2 = "C-style string"; // I realize this is bad style
printString(string("Hello world!")); // All of these work
printString(s1);
printString(string(s2));
printString(string(argv[0]));
MyObject mo1 (string("Hello world!")); // Valid
MyObject mo2 (s1); // Valid
MyObject mo3 (string(s2)); // Does not print
MyObject mo4 (string(argv[0])); // Does not print
mo1.aMethod();
mo2.aMethod();
mo3.aMethod(); // Error
mo4.aMethod(); // Error
return 0;
}
For mo3 and mo4, the objects can be created, but no methods can be used. They are of the wrong typ. It appears that the compiler thinks they are functions...
test.cpp: In function 'int main(int, char**)':
test.cpp:22:13: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
test.cpp:36:5: error: request for member 'aMethod' in 'mo3', which is of non-class type 'MyObject(std::string) {aka MyObject(std::basic_string<char>)}'
test.cpp:37:5: error: request for member 'aMethod' in 'mo4', which is of non-class type 'MyObject(std::string*) {aka MyObject(std::basic_string<char>*)}'

This is just a variation of the most vexing parse: mo3 and mo4 are function declarations rather than object definitions. You can fix the problem using
MyObject mo3 {string(s2)};
MyObject mo4 {string(argv[0])};
or
MyObject mo3 ((string(s2)));
MyObject mo4 ((string(argv[0])));
or
MyObject mo3 = MyObject(string(s2));
MyObject mo4 = MyObject(string(argv[0]));
or ...

Related

explicit conversion to std::function

I'm trying to define explicit conversion from some class to std::function like this:
#include <functional>
class ExpInt { private:
const int value;
public:
ExpInt(const int v):value(v){}
explicit operator std::function<int (void)> ()
{
return [=](void){ return value; };
}
};
int main(int argc, char **argv)
{
auto e = new ExpInt(44);
auto f = static_cast<std::function<int (void)>>(e);
return 0;
}
But when I compile it I get the following error:
$ g++ main.cpp -o main
main.cpp: In function ‘int main(int, char**)’:
main.cpp:16:51: error: no matching function for call to ‘std::function<int()>::function(ExpInt*&)’
auto f = static_cast<std::function<int (void)>>(e);
^
The compiler tells you what's wrong:
error: no matching function for call to ‘std::function<int()>::function(ExpInt*&)’
auto f = static_cast<std::function<int (void)>>(e);
^
A pointer to ExpInt is not convertible to std::function<int (void)>. ExpInt would be convertible, so if you simply indirect through the pointer, that would work:
auto f = static_cast<std::function<int (void)>>(*e);
P.S. You leak the dynamic allocation. Avoid using owning bare pointers.

C++ - Vector of function pointers inside class

I am making my own programming language. I made classes (like 'string' or 'int) that derive from the object class. I am making standard types like string and int so I have a base I can work off (expand my language with itself if that makes sense). Each standard type has a unordered_map of functions. I would love to hear a way to fix this/another approach.
When I run the program, I get this error that I don't understand:
C2664: 'std::pair<const _Kty,_Ty>::pair(std::pair<const _Kty,_Ty> &&)': cannot convert argument 2 from '_Ty' to 'const _Ty2 &'
It's referring to line 62. Where the error comes from:
c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xmemory0 line:881
The code from xmemory0:
template<class _Objty,
class... _Types>
static void construct(_Alloc&, _Objty * const _Ptr, _Types&&... _Args)
{ // construct _Objty(_Types...) at _Ptr
::new (const_cast<void *>(static_cast<const volatile void *>(_Ptr)))
_Objty(_STD forward<_Types>(_Args)...);
}
My code:
#include <iostream>
#include <unordered_map>
#include <string>
#include <functional>
struct Object;
typedef std::unordered_map<std::string, std::function<Object*(std::string*)>> stdtypefunc_map;
struct Object
{
};
struct StdType : public Object
{
stdtypefunc_map functions;
};
struct stringtype : public StdType
{
stringtype()
{
functions.emplace("GetValue", &stringtype::GetValue);
}
Object* GetValue(std::string args[])
{
std::cout << "GetValue()" << std::endl;
}
};
int main()
{
stringtype s;
return 0;
}
In your code, line 62 is this statement:
functions.emplace("GetValue", &stringtype::GetValue);
functions is an std::unordered_map whose key_type is std::string and mapped_type is std::function<Object*(std::string*)>.
emplace() constructs a new std::unordered_map::value_type in the map, passing the values you specify to the value_type's constructor. In this case, that value_type is a std::pair<const std::string, std::function<Object*(std::string*)>>, and you are passing in 2 values to constructor the std::pair with.
The error message you are seeing is basically saying that the compiler can't convert &stringtype::GetValue to std::function<Object*(std::string*)>. For example, here is a simplified example that reproduces the same failure, and GCC gives a VERY DETAILED error message explaining why it failed (which is too large to post here, so I'll post only the relevant pieces):
https://ideone.com/qVLkQd
#include <iostream>
#include <unordered_map>
#include <string>
#include <functional>
struct Object;
typedef std::unordered_map<std::string, std::function<Object*(std::string*)>> stdtypefunc_map;
struct Object
{
};
struct StdType : public Object
{
stdtypefunc_map functions;
};
struct stringtype : public StdType
{
stringtype()
{
functions.emplace("GetValue", &stringtype::GetValue);
}
Object* GetValue(std::string args[])
{
std::cout << "GetValue()" << std::endl;
}
};
int main()
{
stringtype s;
return 0;
}
/usr/include/c++/6/ext/new_allocator.h:120:4: error: no matching function for call to ‘std::pair<const std::__cxx11::basic_string<char>, std::function<Object*(std::__cxx11::basic_string<char>*)> >::pair(const char [9], Object* (stringtype::*)(std::__cxx11::basic_string<char>*))’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
/usr/include/c++/6/ext/new_allocator.h:120:4: note: cannot convert ‘std::forward<Object* (stringtype::*)(std::__cxx11::basic_string<char>*)>((* & __args#1))’ (type ‘Object* (stringtype::*)(std::__cxx11::basic_string<char>*)’) to type ‘const std::function<Object*(std::__cxx11::basic_string<char>*)>&’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
Which makes sense. You can't store a pointer-to-member-method for a non-static method into a std::function unless you take into account that it will need an object instance to call the method on. Such as by using std::bind() to bind an object instance with the pointer-to-member-method:
using std::placeholders::_1;
functions.emplace("GetValue", std::bind(&stringtype::GetValue, this, _1));
Or, by using a lambda to capture the object:
functions.emplace("GetValue", [this](std::string *args){ return this->GetValue(args); });

C++ Inheritance "No Viable Conversion" Error

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));

cannot convert 'int (B::*)(std::string)' to 'int (*)(std::string) ' in assignment pt2function=&B::generate_callback;

I am new to c++, .I am trying to create a pgm that contains 2 classes ,out of which one class has a member function that would generate a callback function in another class though a function pointer, but i keep getting the following error.
#include <iostream>
#include <string>
using namespace std;
class B
{
private: std::string str1;
public: int generate_callback(std::string str1);
};
int B::generate_callback(std::string str1)
{
if ((str1=="Generate")||(str1=="generate"))
{
Cout<<"Callback generated ";
}
return 0;
}
class A : public B
{
public:
void count(int a,int b);
private: int a,b;
};
void A::count(int a, int b)
{
for ( a=1;a<b;a++){
if(a==50)
{
cout<<"Generating callback ";
goto exit;
}
exit: ;
}
}
int (*pt2function)(string)=NULL;
int main()
{
B obj1;
A obj2;
string str;
cout<<"To generate callback at int i=50 please enter 'generate'";
cin>>str;
obj2.count(1,100);
pt2function=&B::generate_callback;
(obj1.*pt2function)(str);
return 0;
}
The errors :
main.cpp:57: error: cannot convert 'int (B::*)(std::string) {aka int (B::*)(std::basic_string<char>)}' to 'int (*)(std::string) {aka int (*)(std::basic_string<char>)}' in assignment
pt2function=&B::generate_callback;
/home/adt/practice/N_practise/n_pract_2/pract2/main.cpp:58: error: 'pt2function' cannot be used as a member pointer, since it is of type 'int (*)(std::string) {aka int (*)(std::basic_string<char>)}'
(obj1.*pt2function)(str);
^
^
The variable pt2function is a pointer to a non-member function. Such a pointer is not compatible with a pointer to a member-function. Which is what the compiler tells you with the first error: A int (*)(string) is not compatible with a int (B::*)(string).
You need to define pt2function as a pointer to a B member function:
int (B::*pt2function)(string)=NULL;
Now you can initialize or assign a matching member function of B to the variable pt2function.
This also solves the second errors, which basically says that in your current code the variable pt2function is not a pointer to a member function, and therefore can not be used as such.
Pointers to functions and pointers to member functions are really different beasts.
You have mainly two options to get it working in your code:
Change this line:
int (*pt2function)(string)=NULL;
To this:
int (B::*pt2function)(string)=NULL;
That is defining pt2function as a pointer to a member function of B that gets a string and returns an int.
Declare the generate_callback as a static method and invoke it as pt2function(str); in your main function.
In fact, a static member function can be assigned to a pointer to function like the one you have already in use.

what does a const char** look like?

I have a class which takes the main command line arguments (eg, -B, -a, etc) and does something with them, but also i would like to be able to instantiate that function without passing the command line arguments, so for example:
constructor:
myClass(int argc, const char **argv){
<initialise class with flags from argv>
}
myClass() : myClass(2, "-B") {}
}
Here i am trying to instantiate myClass with the flag "-B", but it keeps giving me the error:
no known conversion for argument 3 from ‘const char [3]’ to ‘const char**’
so i was wondering what i need to do to pass a value in as const char**?
First level is pointer to first pointer to char *. Second level is pointer to the first const char of c-string.
> cdecl explain "const char ** args"
declare args as pointer to pointer to const char
If you have -std=c++11 available, you can use this example (but it can be rewritten to use old standard):
#include <iostream>
#include <vector>
#include <string>
class test {
public:
test(const std::vector<std::string> & args) {
for (auto & arg : args) {
std::cout << arg << "\n";
}
}
test() : test{{"-B"}} {}
};
int main(int argc, const char ** argv) {
test sth{{argv+1, argc+argv}}; // skip program name here
test sth_else;
}
const char** is pointer to const char*. In your case, you intend to pass multiple arguments as part of argv, so you can pass something like below:
const char* argv[] = {"<program name>", "B"};
myClass m(2, argv);
Note: const char** x & const char* x[] are same. The 2nd syntax is helpful when one wants to "represent" an array.
Here I am giving a way to mimic the main(int, char**) function argument for your internal test. If you want to pass from default constructor to argument constructor then all the above stuff will have to go global.