I have the following two files
foobar.h
#ifndef FOOBAR_H
#define FOOBAR_H
#include <cstring>
class Foo {
public:
int x;
Foo(int x);
};
class Bar {
public:
char* name;
Foo foo;
Bar(Foo foo);
};
#endif // FOOBAR_H
and foobar.cpp
#include "foobar.h"
Foo::Foo(int x) {
// Do something
}
Bar::Bar(Foo foo) {
// Do something
}
Attempting to compile these with g++ -c foobar.cpp -o foobar.o results in the following error:
foobar.cpp: In constructor ‘Bar::Bar(Foo)’:
foobar.cpp:9:17: error: no matching function for call to ‘Foo::Foo()’
Bar::Bar(Foo foo) {
^
foobar.cpp:5:1: note: candidate: ‘Foo::Foo(int)’
Foo::Foo(int x) {
^~~
foobar.cpp:5:1: note: candidate expects 1 argument, 0 provided
In file included from foobar.cpp:1:
foobar.h:5:7: note: candidate: ‘constexpr Foo::Foo(const Foo&)’
class Foo {
^~~
foobar.h:5:7: note: candidate expects 1 argument, 0 provided
foobar.h:5:7: note: candidate: ‘constexpr Foo::Foo(Foo&&)’
foobar.h:5:7: note: candidate expects 1 argument, 0 provided
As far as I understand the output of g++ is that it requires me to have a default constructor for foo. Why? I wish to pass a foo object to the constructor of bar, why would it need to invoke a default constructor anywhere? I do not want to have a no-args constructor anyways, since I NEED that x has a specific user defined value.
You are trying to default construct a Foo here:
Bar::Bar(Foo foo) {
// the member variable `foo` would have been default constructed here
// Do something
}
But Foo doesn't have a default constructor. One possible solution would be to initialize it in the member initializer list:
Bar::Bar(Foo foo) : foo(std::move(foo)) { // now uses the move constructor instead
// Do something
}
Related
I have created the following class which has an object being passed in by reference and is implemented the following way.
Diablo_Serial_4DLib Display(&DisplaySerial);
ZenDisplay ui(Display);
class ZenDisplay
{
public:
ZenDisplay(Diablo_Serial_4DLib &display);
void setup();
private:
Diablo_Serial_4DLib* _display;
};
The constructor is straight forward and works as expected, no problem so far.
// Constructor /////////////////////////////////////////////////////////////////
ZenDisplay::ZenDisplay(Diablo_Serial_4DLib &display)
{
_display = &display;
}
I want to instantiate ZenSpeakerGroup class and pass in the same reference into it's constructor
class ZenSpeakerGroup
{
public:
ZenSpeakerGroup(Diablo_Serial_4DLib &display);
private:
Diablo_Serial_4DLib* _display;
};
ZenSpeakerGroup::ZenSpeakerGroup(Diablo_Serial_4DLib &display)
{
_display = &display;
}
I have modified the original working class to the following
class ZenDisplay
{
public:
ZenDisplay(Diablo_Serial_4DLib &display);
void setup();
private:
Diablo_Serial_4DLib* _display;
ZenSpeakerGroup _speakerGroup;
};
// Constructor /////////////////////////////////////////////////////////////////
ZenDisplay::ZenDisplay(Diablo_Serial_4DLib &display) : _speakerGroup(&display)
{
_display = &display;
}
Now I get the following error and not 100% sure what I am doing wrong.
Arduino: 1.8.16 (Mac OS X), Board: "DOIT ESP32 DEVKIT V1, 80MHz, 921600, None"
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenDisplay.cpp: In constructor 'ZenDisplay::ZenDisplay(Diablo_Serial_4DLib&)':
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenDisplay.cpp:14:78: error: no matching function for call to 'ZenSpeakerGroup::ZenSpeakerGroup(Diablo_Serial_4DLib*)'
ZenDisplay::ZenDisplay(Diablo_Serial_4DLib &display) : _speakerGroup(&display)
^
In file included from /Users/xxx/Documents/Arduino/libraries/ZenOne/ZenDisplay.h:14,
from /Users/xxx/Documents/Arduino/libraries/ZenOne/ZenDisplay.cpp:9:
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenSpeakerGroup.h:18:5: note: candidate: 'ZenSpeakerGroup::ZenSpeakerGroup(Diablo_Serial_4DLib&)'
ZenSpeakerGroup(Diablo_Serial_4DLib &display);
^~~~~~~~~~~~~~~
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenSpeakerGroup.h:18:5: note: no known conversion for argument 1 from 'Diablo_Serial_4DLib*' to 'Diablo_Serial_4DLib&'
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenSpeakerGroup.h:15:7: note: candidate: 'constexpr ZenSpeakerGroup::ZenSpeakerGroup(const ZenSpeakerGroup&)'
class ZenSpeakerGroup
^~~~~~~~~~~~~~~
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenSpeakerGroup.h:15:7: note: no known conversion for argument 1 from 'Diablo_Serial_4DLib*' to 'const ZenSpeakerGroup&'
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenSpeakerGroup.h:15:7: note: candidate: 'constexpr ZenSpeakerGroup::ZenSpeakerGroup(ZenSpeakerGroup&&)'
/Users/xxx/Documents/Arduino/libraries/ZenOne/ZenSpeakerGroup.h:15:7: note: no known conversion for argument 1 from 'Diablo_Serial_4DLib*' to 'ZenSpeakerGroup&&'
exit status 1
Error compiling for board DOIT ESP32 DEVKIT V1.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
I also tried the following with no success.
_speakerGroup = new ZenSpeakerGroup(&display)
I would appreciate some help on this.
This is the correct way of passing the display reference to ZenSpeakerGroup
ZenDisplay::ZenDisplay(Diablo_Serial_4DLib &display) : _speakerGroup(display)
{
_display = &display;
}
I have made this mistake aswell it's a typo
make sure when you want to intialize a reference define it as a refference
class ZenDisplay{
public:
ZenDisplay(Diablo_Serial_4DLib &display);
void setup();
private:
Diablo_Serial_4DLib& _display; // <--make sure this is a refference
};
now initialize the refference
ZenDisplay::ZenDisplay(Diablo_Serial_4DLib &display){
_display = display;
}
I'm currently working on a project in C++ in which I have a list of structs stored in a vector that have a lot processing associated with them. In order to speed things up, I've chosen to split the program across multiple threads, and the lazy way I've chosen to do this is by adding a mutex to each struct in the standard library vector. This way I can have a number of threads iterate over the array and basically take ownership of the individual elements by calling mutex.try_lock(), and either completing the associated processing with that element, or moving onto the next open one.
Before we get started, note that the following actually does work.
#include <mutex>
#include <vector>
struct foo {
int a;
std::mutex b;
};
void working_demo () {
// assign by initializer list
foo f = {.a = 1};
}
int main () {
working_demo();
}
So, I intend to populate my standard vector in a way very similar to above, and it doesn't work.
#include <mutex>
#include <vector>
struct foo {
int a;
std::mutex b;
};
void broken_demo () {
std::vector<foo> bar;
// assign by initializer list
bar.push_back({.a = 1});
}
int main () {
broken_demo();
}
Compiler Error:
clang++ -std=c++11 -Wall -Wextra -Wfatal-errors -pedantic -I./ -c -o demo.o demo.cpp
demo.cpp:13:20: warning: designated initializers are a C99 feature [-Wc99-extensions]
bar.push_back({.a = 1});
^~~~~~
In file included from demo.cpp:1:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/mutex:38:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/tuple:39:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/array:39:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/stdexcept:39:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/string:41:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/allocator.h:46:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33:
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/ext/new_allocator.h:146:8: fatal error: call to implicitly-deleted copy constructor of 'foo'
_Up(std::forward<_Args>(__args)...)))
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/alloc_traits.h:483:24: note: in instantiation of exception specification for
'construct<foo, foo>' requested here
noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:115:21: note: in instantiation of exception specification for 'construct<foo, foo>'
requested here
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_vector.h:1201:9: note: in instantiation of function template specialization
'std::vector<foo, std::allocator<foo> >::emplace_back<foo>' requested here
{ emplace_back(std::move(__x)); }
^
demo.cpp:13:9: note: in instantiation of member function 'std::vector<foo, std::allocator<foo> >::push_back' requested here
bar.push_back({.a = 1});
^
demo.cpp:6:16: note: copy constructor of 'foo' is implicitly deleted because field 'b' has a deleted copy constructor
std::mutex b;
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
mutex(const mutex&) = delete;
^
I'm fairly certain that this is saying the reason this won't work is that the structure is attempting to call the copy constructor for the mutex, which in fact does not have a copy constructor. I explicitly don't want to do be doing this.
My initial thought is that in order to make sure it doesn't even try to call the copy constructor for the mutex, I can create my own constructor for my class and basically explicitly leave out the copying for the mutex. This method would look like this - but it also doesn't work.
#include <mutex>
#include <vector>
struct foo {
foo (int A): a(A) {;}
int a;
std::mutex b;
};
void broken_demo () {
std::vector<foo> bar;
// assign by initializer list
bar.emplace_back(1);
}
int main () {
broken_demo();
}
Compiler Error:
clang++ -std=c++11 -Wall -Wextra -Wfatal-errors -pedantic -I./ -c -o demo.o demo.cpp
In file included from demo.cpp:2:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/vector:65:
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_construct.h:75:38: fatal error: call to implicitly-deleted copy constructor of 'foo'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:83:8: note: in instantiation of function template specialization
'std::_Construct<foo, foo>' requested here
std::_Construct(std::__addressof(*__cur), *__first);
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:134:2: note: in instantiation of function template specialization
'std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<foo *>, foo *>' requested here
__uninit_copy(__first, __last, __result);
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:289:19: note: in instantiation of function template specialization
'std::uninitialized_copy<std::move_iterator<foo *>, foo *>' requested here
{ return std::uninitialized_copy(__first, __last, __result); }
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:310:19: note: in instantiation of function template specialization
'std::__uninitialized_copy_a<std::move_iterator<foo *>, foo *, foo>' requested here
return std::__uninitialized_copy_a
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:473:10: note: in instantiation of function template specialization
'std::__uninitialized_move_if_noexcept_a<foo *, foo *, std::allocator<foo> >' requested here
= std::__uninitialized_move_if_noexcept_a
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:121:4: note: in instantiation of function template specialization 'std::vector<foo,
std::allocator<foo> >::_M_realloc_insert<int>' requested here
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
^
demo.cpp:15:9: note: in instantiation of function template specialization 'std::vector<foo, std::allocator<foo> >::emplace_back<int>' requested here
bar.emplace_back(1);
^
demo.cpp:8:16: note: copy constructor of 'foo' is implicitly deleted because field 'b' has a deleted copy constructor
std::mutex b;
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
mutex(const mutex&) = delete;
^
1 error generated.
Any thoughts on a solution to this? I'm hoping to keep the code relatively simple, but I'm uncertain how to make the standard vector behave, or at least use it properly.
The problem is that in your code instances of foo are passed by value. So when you put something into the vector, a copy needs to be created. A simple way to avoid that would be to put pointers to foo into the vector. You can wrap the pointers into some reference-counting mechanism so that you don't have to keep track of freeing the objects.
Here is a short example using std::unique_ptr that will auto-delete all foo instances in the vector when the vector goes out of scope:
#include <mutex>
#include <vector>
#include <memory>
#include <iostream>
#include <functional>
struct foo {
foo(int A) : a(A) {}
int a;
std::mutex b;
};
void fixed_demo () {
std::vector<std::unique_ptr<foo>> bar;
std::unique_ptr<foo> p(new foo(1));
bar.push_back(std::move(p));
bar.emplace_back(new foo(2));
for (auto it = bar.begin(); it != bar.end(); ++it) {
(*it)->b.lock();
std::cout << (*it)->a << std::endl;
(*it)->b.unlock();
}
}
int main () {
fixed_demo();
return 0;
}
After looking at one of the solutions, I think actually this solution fits best what I was going for. I wouldn't have been able to figure this out without the helpful advice above.
#include <mutex>
#include <vector>
struct foo {
int a;
std::mutex b;
foo (int a) : a(a) {;}
foo (const foo &f) : a(f.a) {;}
};
void other_fixed_demo ()
{
std::vector<foo> bar;
bar.emplace_back(1);
}
int main () {
other_fixed_demo();
}
I couldn't say why, but apparently two things are happening here. First, we are calling the constructor with the 1 input, and then somewhere within emplace_back() we're calling the copy constructor. Both need to explicitly not include the mutex in each way of creating the struct, and the above solution avoids that.
Below is my code:
// this code illustrates iterating through a nested hashmap.
#include <iostream>
#include "imported.hpp"
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
#define MAX_LINE_LENGTH 999
using namespace std;
class State
{
public:
vector<string> vec;
string state_string;
State(string state_string, vector<string> vec);
};
State::State(string state_string, vector<string> vec)
{
this->state_string = state_string;
this->vec = vec;
}
class Heuristic
{
public:
State goal_state;
string type;
Heuristic(string type, State goal_state);
};
Heuristic::Heuristic(string type, State goal_state)
{
this->type = type;
this->goal_state = goal_state;
}
int main(int argc, char const *argv[])
{
}
When I try to compile it using:
g++ filename.cpp
The following output is produced:
$ g++ main.cpp
main.cpp: In constructor ‘Heuristic::Heuristic(std::string, State)’:
main.cpp:36:51: error: no matching function for call to ‘State::State()’
Heuristic::Heuristic(string type, State goal_state)
^
main.cpp:21:1: note: candidate: State::State(std::string, std::vector<std::basic_string<char> >)
State::State(string state_string, vector<string> vec)
^~~~~
main.cpp:21:1: note: candidate expects 2 arguments, 0 provided
main.cpp:12:7: note: candidate: State::State(const State&)
class State
^~~~~
main.cpp:12:7: note: candidate expects 1 argument, 0 provided
main.cpp:12:7: note: candidate: State::State(State&&)
main.cpp:12:7: note: candidate expects 1 argument, 0 provided
I am confused as to why this is happening since I am not even calling the constructor but rather am defining a function's method signature into which the user should be able to pass an existent State object. Please assist.
The Heuristic constructor is built using assignment operators which involves the default construction of its member objects. Since State does not have a default constructor, this form of construction will fail.
There are two ways of solving this:
If the members have user-defined constructors, provide default-constructors also for them .
Use initializer lists for your constructor instead of assignments within the body of the constructor.
Of these two methods, the second one is more preferable. The reasons for this are outlined in the FAQ: Should my constructors use “initialization lists” or “assignment”?
I'm compiling the following code
#include <iostream>
#include <stdexcept>
#include <string>
struct stack_error : public virtual std::logic_error {
using std::logic_error::logic_error;
//explicit stack_error(std::string const& what_arg) : std::logic_error(what_arg) {}
};
struct stack_empty_error : public stack_error {
explicit stack_empty_error(std::string const& what_arg) : std::logic_error(what_arg), stack_error(what_arg) {}
};
struct stack_full_error : public stack_error {
explicit stack_full_error(std::string const& what_arg) : std::logic_error(what_arg), stack_error(what_arg) {}
};
int main() {
stack_full_error e(std::string("WOW"));
std::cout << "ok" << '\n';
return 0;
}
with gcc 6.3 and I don't understand why it gives me the following error
(I think that the using std::error_logic... injects its 2 constructor in stack_error but if I use the commented out code everything is fine.
g++ -std=c++1z -Wall -Wextra -pedantic vbase.cpp -o vbase
(note clang++ compile it without error
clang++ -std=c++1z -Wall -Wextra -pedantic vbase.cpp -o vbase)
vbase.cpp: In constructor 'stack_empty_error::stack_empty_error(const string&)':
vbase.cpp:13:111: error: use of deleted function 'stack_error::stack_error(const string&)'
explicit stack_empty_error(std::string const& what_arg) : std::logic_error(what_arg), stack_error(what_arg) {}
^
vbase.cpp:6:27: note: 'stack_error::stack_error(const string&)' is implicitly deleted because the default definition would be ill-formed:
using std::logic_error::logic_error;
^~~~~~~~~~~
vbase.cpp:6:27: error: no matching function for call to 'std::logic_error::logic_error()'
In file included from C:/msys64/mingw64/include/c++/6.3.0/system_error:41:0,
from C:/msys64/mingw64/include/c++/6.3.0/bits/ios_base.h:46,
from C:/msys64/mingw64/include/c++/6.3.0/ios:42,
from C:/msys64/mingw64/include/c++/6.3.0/ostream:38,
from C:/msys64/mingw64/include/c++/6.3.0/iostream:39,
from vbase.cpp:1:
C:/msys64/mingw64/include/c++/6.3.0/stdexcept:128:5: note: candidate: std::logic_error::logic_error(const std::logic_error&)
logic_error(const logic_error&) _GLIBCXX_USE_NOEXCEPT;
^~~~~~~~~~~
C:/msys64/mingw64/include/c++/6.3.0/stdexcept:128:5: note: candidate expects 1 argument, 0 provided
C:/msys64/mingw64/include/c++/6.3.0/stdexcept:124:5: note: candidate: std::logic_error::logic_error(const char*)
logic_error(const char*) _GLIBCXX_TXN_SAFE;
^~~~~~~~~~~
C:/msys64/mingw64/include/c++/6.3.0/stdexcept:124:5: note: candidate expects 1 argument, 0 provided
C:/msys64/mingw64/include/c++/6.3.0/stdexcept:120:5: note: candidate: std::logic_error::logic_error(const string&)
logic_error(const string& __arg) _GLIBCXX_TXN_SAFE;
^~~~~~~~~~~
C:/msys64/mingw64/include/c++/6.3.0/stdexcept:120:5: note: candidate expects 1 argument, 0 provided
vbase.cpp: In constructor 'stack_full_error::stack_full_error(const string&)':
vbase.cpp:19:110: error: use of deleted function 'stack_error::stack_error(const string&)'
explicit stack_full_error(std::string const& what_arg) : std::logic_error(what_arg), stack_error(what_arg) {}
std::unique_ptr makes compiling error candidate constructor (the implicit copy constructor) not viable
Let me declare it by these code below.
Code that makes compiling error is:
Code0: error
#include <iostream>
class A {
public:
static A str(){ return A();}
std::unique_ptr<int> pi;
A(): pi(new int(0)){}
};
Error is:
test.cpp:4:26: error: no matching constructor for initialization of 'A'
static A str(){ return A();}
^~~
test.cpp:2:7: note: candidate constructor (the implicit copy constructor) not viable: expects an l-value for 1st argument
class A {
^
test.cpp:7:3: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
A(){
^
1 error generated.
But all these examples below are ok
Code1: ok
#include <iostream>
class A {
public:
//static A str(){ return A();}
std::unique_ptr<int> pi;
A(): pi(new int(0)){}
};
Code2: ok
#include <iostream>
class A {
public:
static A str(){ return A();}
//std::unique_ptr<int> pi;
A()/*: pi(new int(0))*/{}
};
Code3: ok
#include <iostream>
class A {
public:
static A str(){ return A();}
std::shared_ptr<int> pi;
A(): pi(new int(0)){}
};
Im using g++, version info
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.1.76)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
Could anyone explain it?