an array of functions of a class - c++

To store the functions of a class in an array the following link http://sourcemaking.com/design_patterns/state/cpp/1 contains the code like below (Machine is the class name).
void(Machine:: *ptrs[])() =
{
Machine::off, Machine::on
};
The example in that link does not compile with the g++ compiler throwing error as below
$ g++ state.cpp
state.cpp: In function ‘int main()’:
state.cpp:89:18: error: invalid use of non-static member function ‘void Machine::off()’
state.cpp:89:32: error: invalid use of non-static member function ‘void Machine::on()’
state.cpp:97:15: error: expected unqualified-id before ‘*’ token
I am using g++ version 4.5.2
$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Can an array be defined like this, i am not able to find an array defination like this any where else. If the example is correct why does not it compile.

If you define a typedef for your member functions you will simplify your code greatly.
class Machine
{
public:
void on(){}
void off(){}
};
int main()
{
typedef void (Machine::*MachineFunctionPtr)();
MachineFunctionPtr temp[] = { &Machine::off , &Machine::on };
//To invoke a function use this syntax
Machine mymachine;
((mymachine).*(temp[1]))();
The being said your error is due to missing "&" before the function name.
If you don't want to use typedef the correct way is something like
void(Machine:: *ptrs[])() =
{
&Machine::off, &Machine::on
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
((fsm).*(ptrs[num]))();
}

To be able to add your member-function-pointers to your array you'll need to prepend their identifiers with the address-of operator &.
Example:
struct Obj {
void func_1 () {}
void func_2 () {}
};
int
main (int argc, char *argv[])
{
void (Obj::* pointers[]) () = {
&Obj::func_1, &Obj::func_2
};
}

This is the more c++ way to do it :
#include <vector>
#include <iostream>
struct A {
typedef void (A::*memfpt)();
A() : arr( { &A::foo, &A::bar } )
{}
void foo()
{
std::cout<<"foo"<<std::endl;
}
void bar()
{
std::cout<<"bar"<<std::endl;
}
std::vector< memfpt > arr;
};
int main() {
A a;
for ( auto &it : a.arr )
{
(a.*it)();
}
}
Instead of raw array, I used std::vector, and instead of that unspeakable abomination, I used the typedef.
Your specific example doesn't compile because :
line 97 : (fsm. *ptrs[num])(); should be (fsm.*ptrs[num])(); - you need to remove that space, because calling a pointer to member function should be done using .* or ->*
line 89 : Machine::off, Machine::on should be &Machine::off, &Machine::on because that is how you get pointer to member function.

Related

error: expected unqualified-id before ‘{’ token on Linux gcc

i get the following error message when trying to compile the following code on linux with gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5) while it works on windows without problems.
...
#include "DDImage/NoIop.h"
static const char* const CLASS = "RemoveChannels";
// -------------------- Header -------------------- \\
class RemoveChannels : public NoIop
{
public:
//! Default constructor.
RemoveChannels (Node* node) : NoIop(node)
{
this->_message = "\\w+";
this->operation = 1;
}
//! Virtual destructor.
virtual ~RemoveChannels () {}
void _validate(bool) override;
private:
//! Information private for the node.
ChannelSet channels;
std::regex rgx;
const char* _message;
int operation; // 0 = remove, 1 = keep
};
void RemoveChannels::_validate(bool for_real)
{
if (!this->_message) // Fast return if you don't have anything in there.
{
set_out_channels(Mask_None); // Tell Nuke we didn't touch anything.
return;
}
...
}
...
When compiling the above code i get the following error message on linux with gcc (on windows it works fine!).
Compiler error:
RemoveChannels.cpp:28:1: error: expected unqualified-id before ‘{’ token
{
^
RemoveChannels.cpp:65:6: error: ‘RemoveChannels’ has not been declared
void RemoveChannels::_validate(bool for_real)
^~~~~~~~~~~~~~
/RemoveChannels.cpp: In function ‘void _validate(bool)’:
RemoveChannels.cpp:67:8: error: invalid use of ‘this’ in non-member function
if (!this->_message) // Fast return if you don't have anything in there.
^~~~
...
If i remove this-> from the implementing function and just use _message it compiles and works without a problem.
Can anyone explain to me why this is happening and just on linux and not on windows?
Simple example
// -------------------- Header --------------------\\
class RemoveChannels
{
public:
int operation = 0;
};
int main ()
{
RemoveChannels r;
r.operation++;
}
when a line ends in a backslash, it is continued on the next line. That means class RemoveChannels has accidentally been commented out with a line comment leaking into the next line.
Solution: remove the backslash
// -------------------- Header --------------------
class RemoveChannels
{
public:
int operation = 0;
};
int main ()
{
RemoveChannels r;
r.operation++;
}

Why does introducing std::mutex to member class generate this compile error?

In the code below, class B contains an array of member class class A.
B::A has one member bool and one member std::thread.
The code below compiles fine:
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A( const bool& b ) : b_( b ) {}
bool b_;
std::thread thread_;
} a_[2];
};
B::B() : a_{ { false }, { false } } { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ --version && g++ -g ./main.cpp
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
Why does introducing a std::mutex to B::A introduce the following compile error?
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A( const bool& b ) : b_( b ) {}
bool b_;
std::mutex mutex_; // I break compilation!
std::thread thread_;
} a_[2];
};
B::B() : a_{ { false }, { false } } { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ -g ./main.cpp
./main.cpp: In constructor ‘B::B()’:
./main.cpp:21:35: error: use of deleted function ‘B::A::A(B::A&&)’
B::B() : a_{ { false }, { false } } { }
^
./main.cpp:11:9: note: ‘B::A::A(B::A&&)’ is implicitly deleted because the default definition would be ill-formed:
class A {
^
./main.cpp:11:9: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’
In file included from /usr/include/c++/6/mutex:44:0,
from ./main.cpp:2:
/usr/include/c++/6/bits/std_mutex.h:97:5: note: declared here
mutex(const mutex&) = delete;
^~~~~
If I correctly understand the compile error, it's complaining that an instance of B::A cannot be created without explicit construction of B::A::mutex_. But if this is true, I don't understand why this should be necessary: std::mutex has a default constructor, so doesn't need any constructor arguments, as demonstrated below:
// main.cpp
#include <mutex>
int main( int argc, char* argv[] ) {
std::mutex mutex[10];
return 0;
}
Please help me understand the nature of the above compile error, and what an appropriate fix might be.
Update: #Jarod42 and #chris seem to have discovered this is a compiler bug. I'm updating the question to ask if anyone could explain the nature of this bug -- initiaizing member array-of-object elements seems like such a simple and foundational thing. What type of objects trigger this bug and why? I can't imagine this could be a universal/easily reproducible problem...?
Update: A not-great workaround seems to be making B::A::A an empty constructor and initializing B::A::b_ with an rvalue. :(
// main.cpp
#include <mutex>
#include <thread>
class B {
public:
B();
private:
class A {
public:
A() : b_( false ) {}
bool b_;
std::mutex mutex_;
std::thread thread_;
} a_[2];
};
B::B() { }
int main( int argc, char* argv[] ) {
B b;
return 0;
}
$ g++ -g ./main.cpp
$
The apparent, likely cause of the bug is a subtle difference between copy-initialization and copy-list-initialization:
struct A {
A(int);
A(A&&)=delete;
} a=1, // error: not movable
b=A(1), // error
c={1}, // OK, no temporary constructed
d[]={1}, // error
e[]={A{1}}, // error
f[]={{1}}; // OK (the compiler bug)
Here a bare 1 is converted to a temporary A which cannot be copied/moved, whereas {1} is used to initialize the ultimate A despite the term “copy”. This distinction vanishes in C++17, where initialization from a prvalue (as for b or a after conversion) invokes only the prvalue’s constructor (“mandatory copy elision”).
The issue also couldn’t arise prior to C++11, since non-static array members could only be default- or value-initialized. (={} was also considered normal copy-initialization then and didn’t apply to class objects at all.) This is why your workaround worked, and the gradual adoption of the new initializers is probably why the compiler bug lasted as long as it did.
Note that, despite the error mentioning std::mutex’s deleted copy constructor, it is its non-movability that matters (as indicated by the B::A::A(B::A&&)), which is how it differs from std::thread.

In what scopes is the "using namespace" clause valid? [duplicate]

This question already has answers here:
Why is "using namespace X;" not allowed at class/struct level?
(6 answers)
Closed 3 years ago.
I once heard/read (reference has slipped my mind; unable to cite it) that the "using namespace" clause is valid in any scope, but it appears to not be valid in a class scope:
// main.cpp
#include <iostream>
namespace foo
{
void func() { std::cout << __FUNCTION__ << std::endl; }
};
class Foo
{
using namespace foo;
public:
Foo() { func(); }
};
int main( int argc, char* argv[] )
{
Foo f;
}
.
$ g++ --version
g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.
$ g++ -g ./main.cpp
./main.cpp:12:7: error: expected nested-name-specifier before 'namespace'
using namespace foo;
^~~~~~~~~
./main.cpp: In constructor 'Foo::Foo()':
./main.cpp:15:13: error: 'func' was not declared in this scope
Foo() { func(); }
^~~~
./main.cpp:15:13: note: suggested alternative:
./main.cpp:7:8: note: 'foo::func'
void func() { std::cout << __FUNCTION__ << std::endl; }
^~~~
$
$ g++ --std=c++11 -g ./main.cpp
./main.cpp:12:7: error: expected nested-name-specifier before 'namespace'
using namespace foo;
^~~~~~~~~
./main.cpp: In constructor 'Foo::Foo()':
./main.cpp:15:13: error: 'func' was not declared in this scope
Foo() { func(); }
^~~~
./main.cpp:15:13: note: suggested alternative:
./main.cpp:7:8: note: 'foo::func'
void func() { std::cout << __FUNCTION__ << std::endl; }
^~~~
The following variation of class Foo results in the same compiler error:
class Foo
{
using namespace ::foo;
public:
Foo()
{
func();
}
};
The following variations of class Foo result in no compiler errors or warning:
class Foo
{
public:
Foo()
{
using namespace foo;
func();
}
};
.
class Foo
{
public:
Foo()
{
foo::func();
}
};
My (incorrect?) understanding of the compiler error, based on reading posts such as this and this, is that error essentially requires full scoping of the used namespace, i.e. what I attempted in the first variation to class Foo, above.
Please note: in addition to explicit use of the --std=c++11 compiler flag, the compiler version used is well above the minimum necessary to not encounter this error (without explicit use of the --std=c++11 compiler flag), according to the noted Stack Overflow Q&A.
What does this compiler error mean (if different than my above-stated understanding) in this context? (My use appears different than that in the two noted Stack Overflow Q&A).
In general: in what scopes is the "using namespace" directive valid?
From cppreference.com:
Using-directives are allowed only in namespace scope and in block scope.
So you can use them within a namespace (including the global namespace) or within a code block. A class declaration is neither of those.

C++ - Errors when trying to insert class into map

I have a map like so map<string, unique_ptr<Base>> variables and I am trying to insert data into the map variables.insert(make_pair("foo", new Int(10))) but I am getting to following errors:
error: no matching function for call to ‘std::map<std::__cxx11::basic_string<char>, std::unique_ptr<Base>>::insert(std::pair<const char*, Int*>)’
variables.insert(make_pair("test", new Int(10)));
error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
template<typename _Pair, typename = typename
This is my code:
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int operator=(int i) {
this->i = i;
}
int i;
};
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
}
I think I need a fresh pair of eyes to look at this I'm not sure what this issue is, thanks!
Edit
I'm trying to make a heterogeneous map and there's a class for each data type. But I still get the same error no matter how many there are.
Note: This answer only applies to older versions of the main three compilers:
GCC: Applies to 5.3.1 or earlier. May apply to any version earlier than 6.1.0, but I haven't tested this.
Clang: Applies to 3.7.1 or earlier. May apply to any version earlier than 3.8.0, but I haven't tested this.
Visual Studio: Applies to 19.00.23506.0 or earlier. May apply to any version earlier than 19.00.23720.0, but I haven't tested this.
Conversely, if you have GCC 6.1.0 or later, Clang 3.8.0 or later, or Visual Studio 19.00.23720.0 or later, the original code should compile as is, without either of the modifications suggested in this answer.
[Thanks goes to AndyG for pointing out that it works with later versions of GCC & Clang.]
The problem appears to be that it isn't creating your unique_ptr from your raw pointer.
If you can use C++14, try std::make_unique().
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", make_unique<Int>(10)));
}
If you can't, then try something like this:
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
}
Interestingly, I noticed a slight difference in how different compilers handle this. Using the following slightly modified version of your code as a test program:
#include <map>
#include <memory>
#include <iostream>
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int& operator=(int i) {
this->i = i;
// You forgot to return something.
return *this;
}
int i;
};
void set() {
using namespace std;
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
// C++14:
// variables.insert(make_pair("test", make_unique<Int>(10)));
// C++11:
// variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
// Cheap hack for testing.
cout << static_cast<Int*>(variables["test"].get())->i << endl;
}
int main() {
set();
}
Most compilers* will fail to compile this, unless the initial line is commented out and either of the fixes is uncommented. However, the online MSVC compiler seemed to be able to compile it fine, without needing to uncomment either of the lines. Curiously, the version of MSVC available on Rextester failed to compile it without uncommenting one of the two lines.
* Tested online, with TutorialsPoint GCC, MSVC 2015 online, and Rextester Clang, GCC, and MSVC.

In C, assignment of function pointer to appropriately-typed variable gives "cannot convert ... in assignment"

Take the following C/C++ code:
#include <stdlib.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*foo(bool))(int); // foo is &(bool→(int→int))
foo = baz;
}
Attempting to compile this (gcc or g++) gives:
$ g++ test.cc
test.cc: In function ‘int main()’:
test.cc:9: error: assignment of function ‘int (* foo(bool))(int)’
test.cc:9: error: cannot convert ‘int (*(bool))(int)’ to ‘int (*(bool))(int)’ in assignment
Check for yourself: the two types it claims it cannot convert between are exactly the same. Why then is it claiming that they are incompatible?
EDIT 1: The problem disappears when using typedefs (as is recommended), like so:
int main() {
typedef int (*int2int)(int);
typedef int2int (*bool2_int2int)(bool);
bool2_int2int foo;
foo = baz;
}
EDIT 2: The compiler, of course, was right. The problem with my original code, as many pointed out, is that foo in main() is a declaration of a function, and not a function pointer. The error in the assignment was therefore not conflicting types but assigning to a function, which is not possible. The correct code is:
#include <stdlib.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*(*foo)(bool))(int); // foo is &(bool→(int→int))
foo = &baz;
}
The code is in fact wrong. The problem is that this line:
int (*foo(bool))(int); // foo is &(bool→(int→int))
... doesn't mean what you think it means. It's interpreted as a declaration of a function named "foo". That makes perfect sense. Think about it - if you had wanted to forward declare "baz", you would have put int (*baz(bool))(int); , right? Also, since baz is a function which returns a function pointer, and foo is a pointer to a function which returns a function pointer, wouldn't you expect the syntax to be more complicated?
You declared foo as a function of the same type as baz, rather than as a pointer to a function of same type as baz.
From your compiler, the first error message is the useful one - it tells you assignment of function, i.e. you have tried to assign to a function, which is an error.
I'm not even going to try to write the correct solution without typedefs :-) Here's some code which compiles and I think is right, using typedefs:
#include <stdlib.h>
#include <stdbool.h>
typedef int(*IntReturnsInt)(int);
int inc(int i) { return i+1; }
IntReturnsInt baz(bool b) { return b ? &abs : &inc; }
int main() {
IntReturnsInt (*foo)(bool b);
foo = baz;
}
In this example the double-function-pointer concept is a bit clearer - IntReturnsInt is a function pointer type and foo is a pointer to a function which returns IntReturnsInt... phew :-)
This is a function declaration.
int (*foo(bool))(int);
If you wanted to declare a function pointer, you should do:
int (*(*foo)(bool))(int);
It's difficult to be sure, but I think this is closer to the OP's intent:
// baz is a function returning a pointer to a function
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
// foo is a pointer to a function
int (*foo)(int) ;
foo = baz(true); // Now foo is equal to &abs
}
you cannot assign to function type (int (*foo(bool))(int);), you need to use pointer to function
int (*(*foo)(bool))(int);
foo = &baz;
#include <stdlib.h>
#include <stdbool.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*(*foo)(bool))(int); // foo is &(bool→(int→int))
foo = baz;
return 0;
}
So there were a few side-issues clouding the core issue. Your "bool" was being interpreted as a default-int untyped parameter because the actual built-in is _Bool, humanized by the previously-missing #include <stdbool.h>. The lack of a pointer declaration for the object on the stack was confounding its ability to conform to the type of the real function object in static memory just above.
Once I included <stdbool.h>, the error shifted to "lvalue required" complaint, because there was only a function declaration and not a pointer object. The code above will compile with no warnings or errors.