I am having difficulty accessing a non-static member function from a function pointer and can't quite figure out my syntax issue. When attempting to compile as seen below I receive "error: fnc_ptr not declared in this scope." and when if the code is modified to not access the function it should point to it compiles and will print out 1 for bar.fn_ptr .To compile I used:
g++ -std=c++11 -Wall example.cpp foo.cpp
The split file structure/namespace is just meant to emulate the same conditions as my original issue.
example.cpp
#include "foo.h"
#include <iostream>
int main(int argc, char* argv[]){
pizza::foo bar;
bar.fn_ptr = &pizza::foo::fnc_one;
std::cout << (bar.*fn_ptr)(1) << std::endl;
return 0;
}
foo.cpp
#include <cmath>
#include "foo.h"
namespace pizza{
double foo::fnc_one(double x){
return pow(x,3) - x + 2;
}
}
foo.h
namespace pizza{
class foo{
public:
double (foo::*fn_ptr)(double);
double fnc_one(double);
foo(){
fn_ptr = 0;
}
};
}
A very similar question can be found here, with additional reference here.
You are missing bar. when referring to fn_ptr which is an attribute of that object. Change it to:
std::cout << (bar.*(bar.fn_ptr))(1) << std::endl;
And it works.
I also recommend reading this FAQ on the subject: https://isocpp.org/wiki/faq/pointers-to-members
I believe the correct syntax is:
//std::cout << (bar.*fn_ptr)(1) << std::endl;
std::cout << (bar.*(bar.fn_ptr))(1) << std::endl;
Related
I bulit it with -std=c++17 and tried both g++ and clang++ such as clang++ -std=c++17 <file>. It showed the same results.
unordered_map
Pass an unordered_map to rvalue parameter in a function and assign it to another reference. And the memory is not allowed out of the function.
#include <iostream>
#include <string>
#include <unordered_map>
#include <list>
using namespace std;
typedef unordered_map<string, string> kw_t;
struct Bar {
kw_t &foo;
string bar;
};
list<Bar> bars;
void test(kw_t &&foo) {
cout << &foo["a"] << endl;
bars.emplace_back(Bar { .foo = foo, .bar = "bar" });
cout << &bars.front().foo["a"] << endl;
}
int main()
{
test({{"a", "b"}});
cout << &bars.front().foo["a"] << endl;
return 0;
}
And it has output:
0x1f3ded8
0x1f3ded8
[1] 9776 segmentation fault (core dumped) ./a.o
list
But for other classes, such as list or self defined struct, the code can work.
#include <iostream>
#include <list>
#include <string>
using namespace std;
typedef list<string> args_t;
struct Bar {
args_t &foo;
string bar;
};
list<Bar> bars;
void test(args_t &&foo) {
cout << &foo.front() << endl;
bars.emplace_back(Bar { .foo = foo, .bar = "bar" });
cout << &bars.front().foo.front() << endl;
}
int main()
{
test({"a", "b"});
cout << &bars.front().foo.front() << endl;
return 0;
}
It printed:
0x15a7ec0
0x15a7ec0
0x15a7ec0
Why can the second one work but the first not?
Edit1:
clang version 7.1.0
g++ (GCC) 9.3.0
Why can the second one work but the first not?
In both cases, behaviour of the program is undefined. So, it "can" or "may" or "is allowed to" appear to work (for whatever you perceive as "woking"). Or to not "work". Or to have any other behaviour.
To clarify, the lifetime of the temporary object to which the reference bars.front().foo was bound has ended, and so the reference is invalid. Calling a member function through the invalid reference results in undefined behaviour.
Is it an erroneous behavior for compiler?
No. The compiler is behaving correctly. Your programs however are broken.
I am learning C++ on a linux machine. I just tried “int i();” to declare a function but I forgot to define it. But to my surprise, this code can be compiled and output 1. I feel very confused. I tried “int I{};”, it still compiled with no errors. Please help to explain. Thanks in advance.
//test1.cpp
#include <iostream>
int main(void)
{
int i{};
std::cout << i << std::endl;
return 0;
}
g++ test1.cpp
./a.out
Output is: 0
//test2.cpp
#include <iostream>
int main(void)
{
int i();
std::cout << i << std::endl;
return 0;
}
g++ test2.cpp
./a.out
Output is : 1
In your first example, you define a variable named i, and value-initialise it, which for int means zero-initialisation.
int i{}; // defines i, initialised to zero
In your second example, you declare a function named i, which takes no parameters, and return int:
int i(); // declares a function
When you print this:
std::cout << i << std::endl;
i first get converted to bool (i decays to a function non-nullptr pointer, then it becomes true), and then printed as an integer, that's why you get 1. The compiler can make this conversion without the definition of i (as the result is always true), that's why you got no linker error.
If your intent was to call this function, and print the result, you'll need to use i():
std::cout << i() << std::endl;
This, of course, needs i's definition.
In your code:
//test1.cpp
#include <iostream>
int main(void)
{
int i{};
std::cout << i << std::endl;
return 0;
}
You are not actually declaring a function without defining it. The line of code int i{}; within the main() function here is a variable of type int named i and you are using a brace initializer list to initialize the variable i with out any values and in most cases could be 0 but can vary by compiler.
//test2.cpp
#include <iostream>
int main(void)
{
int i();
std::cout << i << std::endl;
return 0;
}
In this situation it is basically the same thing. You are within main() and by the rules of the language "you can not declare-define a function within a function", so this results in a declaration - definition of a variable. The only difference here is you are not using a brace initializer list here you are using it's ctor constructor called value initialization. Again you are not passing any values to it and in your case it's assigning an arbitrary value of 1.
Now if your code looked like this:
#include <iostream>
int i();
int main() {
std::cout << i() << '\n';
return 0;
}
This would fail to compile because the function i is declared but not defined. However if you did this:
#include <iostream>
// The text in quotes is not meant to be a string literal. It
// is the message of the text that represents any integer X.
int i() { return /*"some int value"*/ 1; }
int main() {
std::cout << i() << '\n';
return 0;
}
This would compile and run perfectly fine because the function i is both declared and defined.
I created a shared lib, in which I defined a class Foo. In class Foo, there is a function named sayHi(). My question is once I created a Foo object foo, how can I call sayHi() of it. I put my code here.
mylib.h
#ifndef FUNTEST_MYLIB_H
#define FUNTEST_MYLIB_H
class Foo {
public:
int id = 0;
void sayHi();
};
#endif //FUNTEST_MYLIB_H
mylib.cpp
#include <iostream>
#include "mylib.h"
using namespace std;
void Foo::sayHi()
{
cout << "Implemented by lib" << endl;
cout << "id is: " << id << endl;
}
Foo* create()
{
return new Foo();
}
then I use the following commands compile the shared lib:
g++ -c -std=gnu++11 -fPIC mylib.cpp
g++ -shared -fPIC -o mylib.so mylib.o
At the client side, I write two files:
mylib2.cpp
#include <iostream>
#include "mylib.h"
using namespace std;
void Foo::sayHi() {
cout << "Implemented by caller" << endl;
cout << "id is: " << id << endl;
}
main.cpp
#include <iostream>
#include <dlfcn.h>
#include "mylib.h"
using namespace std;
Foo* (*create)();
void (*sayHi)();
int main() {
void* lib = dlopen("./mylib.so", RTLD_LAZY);
create = (Foo* (*)())dlsym(lib, "_Z6createv");
sayHi = (void (*)())dlsym(lib, "_ZN3Foo5sayHiEv");
Foo* foo = create();
sayHi();
foo->sayHi();
foo->id = 100;
cout << "Set id to " << foo->id << endl;
/*
*
* how can I make the follow statement 'sayHi();'
* output the following content:
* Implemented by lib
* id is: 100
*/
sayHi(); // line 29, FIXME
foo->sayHi();
return 0;
}
compile the client with following command:
g++ -std=gnu++11 main.cpp mylib.h mylib2.cpp -ldl
finally run the client:
./a.out
the output is:
Implemented by lib
id is: 0
Implemented by caller
id is: 0
Set id to 100
Implemented by lib
id is: -1407102376 // FIXME
Implemented by caller
id is: 100
how can I make the statement 'sayHi();' at line 29 output the following content:
Implemented by lib
id is: 100
I know if i call the sayHi() function directly, without the foo object, the output will be wrong. But how can I fix it?
The declaration of the sayHi global variable in main.cpp is wrong. You're declaring it as a function pointer. However, since it points to a member function, it needs to be a member function pointer.
void (Foo::*sayHi)();
Then when you call it you need a Foo object:
(foo->*sayHi)();
Alternatively, if you make the sayHi method virtual, you shouldn't need to load the symbol for it at all, since that will be effectively handled by the vtable.
I have succeeded writing a class like this one, capturing this in a lambda defined as non-static attribute of said class:
#include <memory>
#include <iostream>
#include <functional>
struct S
{
S()
{
std::cout << "S::S()[" << this << "]" << std::endl;
}
std::string y_{"hi mate"};
int x_;
std::function<void(int*)> del_{[this](int *ptr)
{
std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
}};
std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};
int main()
{
S s;
}
This compiles and seems to run just fine.
However, with a templated class, it doesn't work anymore:
#include <memory>
#include <iostream>
#include <functional>
template <typename>
struct S
{
S()
{
std::cout << "S::S()[" << this << "]" << std::endl;
}
std::string y_{"hi mate"};
int x_;
std::function<void(int*)> del_{[this](int *ptr)
{
std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
}};
std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};
int main()
{
S<int> s;
}
$> g++ -std=c++1y custom_deleter_template.cpp
~/test custom_deleter_template.cpp: In instantiation of ‘struct
S::’: custom_deleter_template.cpp:9:3: required
from ‘S< >::S() [with
= int]’ custom_deleter_template.cpp:24:10:
required from here custom_deleter_template.cpp:15:35: internal
compiler error: in tsubst_copy, at cp/pt.c:12569
std::function del_{[this](int *ptr)
^ Please submit a full bug report, with preprocessed source if appropriate. See
for instructions.
Preprocessed source stored into /tmp/pyro/ccxfNspM.out file, please
attach this to your bugreport.
Before filing a bugreport (which I can't do, they blocked account creation), is it normal that it does not compile, based on what the standard says?
Compiler is g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2, used flag -std=c++1y. Same thing happens with flag -std=c++11.
This is indeed a bug in GCC, which is already being tracked.
It seems to affect 4.8 and 4.9. As pointed out in the comments this particular example works fine for 4.7 and 5.0. You can see that for yourself here and play with the different versions of gcc.
However this reduced version of your code with no external dependency still crashes with 5.0:
template <typename>
struct S {
int f{[this](){return 42;}()};
};
int main(){
return S<int>{}.f; // should return 42
}
I would suggest that you wait for the bug I referenced to be fixed before using your code, or switch to another compiler ;).
I've got a simple problem I think. But I am unable to solve it so far as I am new to C++ programming. I have created a new C++ project to make the code as short and simple as possible (because the original code is much much longer) while keeping the problem I have. I have searched on Stackoverflow and Google and read about 50 related problems but nothing so far helped me fix it. Putting everything in one cc and one h file works, but is not what I prefer doing. Thanks in advance for the help.
I am using Ubuntu 14.04 / Code::Blocks 13.12 / gcc and g++ 4.8.2
The problem is that I want to access the function inside a class defined in a different file and while compiling works (due to the extern in file1.h) linking fails. If I just put "Simple S1;" instead of "extern Simple S1;" in file1.h and remove it from file1.cc I get a multiple declaration error which is expected. Apparently the "extern" trick doesn't work with classes while it works great with variables.
file1.h:
#ifndef FILE1_H
#define FILE1_H
class Simple
{
private:
unsigned int length = 10;
public:
void SetLength(unsigned int l) {length = l;}
unsigned int GetLength() {return length;}
};
extern Simple S1;
#endif
file1.cc:
#include <iostream>
#include "file1.h"
#include "file2.h"
int main()
{
Simple S1;
unsigned int l = GetL();
std::cout << "length=" << l << "\n";
l = 20;
l = GetL();
std::cout << "length=" << l << "\n";
return 0;
}
file2.h:
#ifndef FILE2_H
#define FILE2_H
unsigned int GetL();
#endif
file2.cc:
#include "file1.h"
#include "file2.h"
unsigned int GetL()
{
return S1.GetLength();
}
build commands and error:
g++ -std=c++11 -Wall -fexceptions -g -c file1.cc -o obj/Debug/file1.o
g++ -std=c++11 -Wall -fexceptions -g -c file2.cc -o obj/Debug/file2.o
g++ -o bin/Debug/Test obj/Debug/file1.o obj/Debug/file2.o
obj/Debug/file2.o: In function `GetL()':
file2.cc:6: undefined reference to `S1'
collect2: error: ld returned 1 exit status
If S1 is global it must be defined at global scope, not inside main() which creates a new instance local to that function.
Put Simple S1; before main() in your function.
#include <iostream>
#include "file1.h"
#include "file2.h"
Simple S1;
int main()
{
unsigned int l = GetL();
std::cout << "length=" << l << "\n";
l = 20;
l = GetL();
std::cout << "length=" << l << "\n";
return 0;
}
extern Simple S1;
This declaration promises there is a global object S1 of type Simple somewhere else in the code. But you never define such an object. The "closest" you come to that is the local variable S1 inside main(), but of course, that's an entirely different things.
So just move the definition of S1 outside of main():
Simple S1;
int main()
{
unsigned int l = GetL();
std::cout << "length=" << l << "\n";
l = 20;
l = GetL();
std::cout << "length=" << l << "\n";
return 0;
}