my error: no matching function for call to ‘Kt::Kt(int&, int)’
I can't figure out what is causing this error. It occurs in the first function where all the getline calls are. The compiler is specifically calling out the third, fifth, and last one, but I'm pretty sure there is something wrong with all of them.
main.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Kt
{
int key = -1;
int count = 0;
};
int kthBiggestFrequency(std::vector<int> a, int k)
{
vector<Kt> *arr = new vector<Kt>;
for (auto &&item : a)
{
if (arr -> empty())
{
arr -> emplace_back(item, 1);
}
else
{
for (auto &&i : *arr)
{
if (item == i.key)
{
i.count++;
}
else
{
arr -> push_back({item, 1});
}
}
}
}
return 1;
}
int main()
{
vector<int> arr{1,1,1,3,2,3,2,4,4,4,1};
int k = 1;
kthBiggestFrequency(arr, k);
}
I need support. I don't know how i can fix it.
my output
[main.cpp 2020-03-14 10:06:15.338]
,,In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
from /usr/include/c++/7/bits/allocator.h:46,
from /usr/include/c++/7/string:41,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:1:
/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘void
__gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Kt; _Args = {int&,
int}; _Tp = Kt]’:
/usr/include/c++/7/bits/alloc_traits.h:475:4: required from ‘static void
std::allocator_traits<std::allocator<_CharT>
>::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&&
...) [with _Up = Kt; _Args = {int&, int}; _Tp = Kt;
std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<Kt>]’
/usr/include/c++/7/bits/vector.tcc:100:30: required from ‘void std::vector<_Tp,
_Alloc>::emplace_back(_Args&& ...) [with _Args = {int&, int}; _Tp = Kt; _Alloc =
std::allocator<Kt>]’
main.cpp:30:40: required from here
/usr/include/c++/7/ext/new_allocator.h:136:4: error: no matching function for call to
‘Kt::Kt(int&, int)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:8:8: note: candidate: constexpr Kt::Kt()
struct Kt
^~
main.cpp:8:8: note: candidate expects 0 arguments, 2 provided
main.cpp:8:8: note: candidate: constexpr Kt::Kt(const Kt&)
main.cpp:8:8: note: candidate expects 1 argument, 2 provided
main.cpp:8:8: note: candidate: constexpr Kt::Kt(Kt&&)
main.cpp:8:8: note: candidate expects 1 argument, 2 provided
how to fix it?
The line arr->emplace_back(item, 1); tries to access the constructor Kt::Kt(int&, int) and fails because this constructor doesn't exists. You can fix it by creating this constructor or by using push_back instead of emplace_back.
To create this constructor:
struct Kt {
int key = -1;
int count = 0;
Kt(int &k, int c) : key(k), count(c) {}
//Kt(int k, int c) : key(k), count(c) {} // Will work too
};
To use push_back:
arr->push_back({item, 1});
One more thing, don't forget to release the allocation of the vector inside the function, and in general try to avoid dynamic allocations (or do it with smart pointers to avoid such mistakes).
Related
This question already has answers here:
how to do an if else depending type of type in c++ template? [duplicate]
(6 answers)
using std::is_same, why my function still can't work for 2 types
(4 answers)
Closed 1 year ago.
I want to fill a vector with different functions depending on the data type of vector. Now I have three types to consider: int, double, string. If I only consider int and double, the code works perfectly. But if I include string into the template, the code fails. I don't understand why the if statement for string doesn't work. Here is the code:
#include <iostream>
#include <vector>
#include <map>
#include <string>
template <typename T>
void fillV(std::vector<T> &res) {
if (std::is_same<T, double>::value ) res.push_back(3.5);
else if (std::is_same<T, int>::value) res.push_back(2);
else if (std::is_same<T, std::string>::value) res.push_back(std::string("hello"));
}
int main()
{
std::vector<std::string> t;
std::vector<double> t1;
std::vector<int> t2;
fillV<std::string>(t);
fillV<double>(t1);
fillV<int>(t2);
std::cout << t[0] << "\n";
std::cout << t1[0] << "\n";
std::cout << t2[0] << "\n";
}
The error information is
input
stderr
Compilation failed due to following error(s).main.cpp: In instantiation of ‘void fillV(std::vector<T>&) [with T = std::basic_string<char>]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',27)">main.cpp:27:25</span>: required from here
main.cpp:16:42: error: no matching function for call to ‘std::vector >::push_back(double)’
if (std::is_same<T, double>::value ) res.push_back(3.5);
^~~
In file included from /usr/include/c++/6/vector:64:0,
from main.cpp:10:
/usr/include/c++/6/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::basic_string; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::basic_string]
push_back(const value_type& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:914:7: note: no known conversion for argument 1 from ‘double’ to ‘const value_type& {aka const std::basic_string&}’
/usr/include/c++/6/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::basic_string; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::basic_string]
push_back(value_type&& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:932:7: note: no known conversion for argument 1 from ‘double’ to ‘std::vector >::value_type&& {aka std::basic_string&&}’
main.cpp:17:43: error: no matching function for call to ‘std::vector >::push_back(int)’
else if (std::is_same<T, int>::value) res.push_back(2);
^~~
In file included from /usr/include/c++/6/vector:64:0,
from main.cpp:10:
/usr/include/c++/6/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::basic_string; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::basic_string]
push_back(const value_type& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:914:7: note: no known conversion for argument 1 from ‘int’ to ‘const value_type& {aka const std::basic_string&}’
/usr/include/c++/6/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::basic_string; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::basic_string]
push_back(value_type&& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:932:7: note: no known conversion for argument 1 from ‘int’ to ‘std::vector >::value_type&& {aka std::basic_string&&}’
main.cpp: In instantiation of ‘void fillV(std::vector<T>&) [with T = double]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',28)">main.cpp:28:21</span>: required from here
main.cpp:18:51: error: no matching function for call to ‘std::vector::push_back(std::string)’
else if (std::is_same<T, std::string>::value) res.push_back(std::string("hello"));
^~~
In file included from /usr/include/c++/6/vector:64:0,
from main.cpp:10:
/usr/include/c++/6/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = double; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = double]
push_back(const value_type& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:914:7: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string}’ to ‘const value_type& {aka const double&}’
/usr/include/c++/6/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = double; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = double]
push_back(value_type&& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:932:7: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string}’ to ‘std::vector::value_type&& {aka double&&}’
main.cpp: In instantiation of ‘void fillV(std::vector<T>&) [with T = int]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',29)">main.cpp:29:18</span>: required from here
main.cpp:18:51: error: no matching function for call to ‘std::vector::push_back(std::string)’
else if (std::is_same<T, std::string>::value) res.push_back(std::string("hello"));
^~~
In file included from /usr/include/c++/6/vector:64:0,
from main.cpp:10:
/usr/include/c++/6/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = int; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = int]
push_back(const value_type& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:914:7: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string}’ to ‘const value_type& {aka const int&}’
/usr/include/c++/6/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = int; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = int]
push_back(value_type&& __x)
^~~~~~~~~
/usr/include/c++/6/bits/stl_vector.h:932:7: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string}’ to ‘std::vector::value_type&& {aka int&&}’
Updated on 04/14/2021:
Since I can't answer my own question, I will add one more solution other than the overloading, which is by Partial template specialization. It works before C++17. The code is inspired by the first answer, thank you.
template <typename T, int i>
struct test;
template <typename T>
struct test<T, 1> {
void fillV(std::vector<T> &res) {
res.push_back(3.5);
}
};
template <typename T>
struct test<T, 2> {
void fillV(std::vector<T> &res) {
res.push_back(2);
}
};
template <typename T>
struct test<T, 3> {
void fillV(std::vector<T> &res) {
res.push_back("Hello");
}
};
int main()
{
std::vector<std::string> t;
std::vector<double> t1;
std::vector<int32_t> t2;
test<double, 1> a1;
a1.fillV(t1);
test<int32_t, 2> a2;
a2.fillV(t2);
test<std::string, 3> a;
a.fillV(t);
std::cout << t[0] << "\n";
std::cout << t1[0] << "\n";
std::cout << t2[0] << "\n";
}
Updated on 04/17/2021:
Moreover, if overloading is used, the following code would be enough.
void fill_v(std::vector<double>& res) { res.push_back(3.5); }
void fill_v(std::vector<int>& res) { res.push_back(2); }
void fill_v(std::vector<std::string>& res) { res.push_back(std::string("hello")); }
int main()
{
std::vector<std::string> t;
std::vector<double> t1;
std::vector<int32_t> t2;
fillV(t1);
fillV(t2);
fillV(t);
std::cout << t[0] << "\n";
std::cout << t1[0] << "\n";
std::cout << t2[0] << "\n";
}
if performs dispatch at run-time. At compile time, all the if part and else part need to be valid whatever T is.
You can change to Constexpr If (since C++17).
If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.
If a constexpr if statement appears inside a templated entity, and if condition is not value-dependent after instantiation, the discarded statement is not instantiated when the enclosing template is instantiated.
E.g.
template <typename T>
void fillV(std::vector<T> &res) {
if constexpr (std::is_same<T, double>::value ) res.push_back(3.5);
else if constexpr (std::is_same<T, int>::value) res.push_back(2);
else if constexpr (std::is_same<T, std::string>::value) res.push_back(std::string("hello"));
}
LIVE
Before C++17, you can add some overloads processing different variants of std::vector. E.g.
void fill_v(std::vector<double>& res) { res.push_back(3.5); }
void fill_v(std::vector<int>& res) { res.push_back(2); }
void fill_v(std::vector<std::string>& res) { res.push_back(std::string("hello")); }
template <typename T>
void fillV(std::vector<T> &res) {
if (std::is_same<T, double>::value ) fill_v(res);
else if (std::is_same<T, int>::value) fill_v(res);
else if (std::is_same<T, std::string>::value) fill_v(res);
// or just
// fill_v(res);
}
UPD: So the gist of the solution: If copy constructor exists it prevents move constructor from being called by std::move. Problem solved.
I've tried to write a "thread safe stack" accordingly to lecturer's requirements:
It should store type itself.
For primitive types it should receive/return by copy (as usual in c)
For class-type it shouldn't call redundant copy-constructor on recieve/return. Use shared_ptr to achieve this.
And I can't make number 3 work.
To be more specific: I don't know how to pass shared_ptr to/from such-designed class. And moreover I'm almost sure I've written the class itself syntactically wrong.
#ifndef SAFE_QUEUE
#define SAFE_QUEUE
#include <condition_variable>
#include <thread>
#include <stdlib.h>
#include <queue>
#include <mutex>
#include <chrono>
template<typename T>
class SafeQueue {
public:
SafeQueue() {
printf("CONSTRUCTOR\n");
}
~SafeQueue() {
printf("DESTRUCTOR\n");
}
void push(T data) {
std::unique_lock<std::mutex> lock(_m);
_queue.push(data);
printf("Pushed %d\n", data);
_cv.notify_one();
}
void push(std::shared_ptr<T> data) {
std::unique_lock<std::mutex> lock(_m);
_queue.push(*data);
_cv.notify_one();
}
bool pop_top(T &outEl) {
std::unique_lock<std::mutex> lock(_m);
while (1) {
bool a;
if (a = this->_cv.wait_for(lock, std::chrono::milliseconds(1000),
[this]() -> bool { return !(this->_queue.empty()); })) {
printf(" \n\n//Wait for returned %d \n", a);
if (!(_queue.empty())) {
outEl = _queue.front();
_queue.pop();
return true;
} else {
continue;
}
} else {
printf(" \n\n//Wait for returned %d \n", a);
printf("Queue is empty\n");
return false;
}
}
}
std::shared_ptr<T> pop_top() {
std::unique_lock<std::mutex> lock(_m);
while (1) {
bool a;
if (a = this->_cv.wait_for(lock, std::chrono::milliseconds(1000),
[this]() -> bool { return !(this->_queue.empty()); })) {
printf(" \n\n//Wait for returned %d \n", a);
if (!(_queue.empty())) {
std::shared_ptr<T> cur = std::make_shared<T>(_queue.front());
_queue.pop();
return cur;
} else {
continue;
}
} else {
printf(" \n\n//Wait for returned %d \n", a);
printf("Queue is empty\n");
return nullptr;
}
}
}
private:
std::queue<T> _queue;
std::condition_variable _cv;
std::mutex _m;
};
#endif
main:
#include <iostream>
#include "safeQueue.h"
#include <vector>
void forEven(SafeQueue<int> *sq, int numThread){
// for(int i=0;i<3;i++)
// sq->push(i+numThread);
// sq->push(1);
// for(int i=0;i<2;i++)
//sq->push(numThread);
int z;
if(sq->pop_top(z))
printf("even popped:%d\n", z);
sq->push(numThread);
printf("even pushed:%d\n", numThread);
}
class myclass{
public:
int val;
myclass(myclass &obj){
printf("copy constructor");
}
myclass(int val):val(val){
printf("constructor");
}
~myclass(){
printf("destructor");
}
};
void forOdd(SafeQueue<int> *sq, int numThread){
int z;
if(sq->pop_top(z))
printf("odd popped:%d\n", z);
if(sq->pop_top(z))
printf("odd popped:%d\n", z);
for(int i=0;i<2;i++) {
sq->push(i + numThread);
printf("odd pushed:%d\n", i + numThread);
}
if(sq->pop_top(z))
printf("odd popped:%d\n", z);
if(sq->pop_top(z))
printf("odd popped:%d\n", z);
}
void forEven_class(SafeQueue<myclass> *sq, myclass &el){
// for(int i=0;i<3;i++)
// sq->push(i+numThread);
// sq->push(1);
// for(int i=0;i<2;i++)
//sq->push(numThread);
std::shared_ptr<myclass> z = std::move(sq->pop_top());
if(z)
printf("even popped:%d\n", z->val);
sq->push(std::make_shared<myclass>(el));
printf("even pushed:%d\n", el.val);
}
void forOdd_class(SafeQueue<myclass> *sq, myclass &el){
std::shared_ptr<myclass> z = std::move(sq->pop_top());
if(z)
printf("odd popped:%d\n", z->val);
z = std::move(sq->pop_top());
if(z)
printf("odd popped:%d\n", z->val);
for(int i=0;i<2;i++) {
sq->push(std::make_shared<myclass>(i + el.val));
printf("odd pushed:%d\n", i + el.val);
}
z = std::move(sq->pop_top());
if(z)
printf("odd popped:%d\n", z->val);
z = std::move(sq->pop_top());
if(z)
printf("odd popped:%d\n", z->val);
}
int main(){
SafeQueue<int> sq;
SafeQueue<myclass> sq_c;
std::vector<std::thread> v_t;
for(int i=0;i<5;i++){
if( i%2 )
v_t.push_back(move(std::thread(forOdd,&sq,i+1)));
else
v_t.push_back(move(std::thread(forEven,&sq,i+1)));
}
for(int i=0;i<5;i++){
v_t[i].join();
}
std::cout << "class test" <<std::endl;
for(int i=0;i<5;i++){
if( i%2 )
v_t.push_back(move(std::thread(forOdd_class,&sq_c,std::move(myclass(i+1)))));
else
v_t.push_back(move(std::thread(forEven_class,&sq_c,std::move(myclass(i+1)))));
}
for(int i=0;i<5;i++){
v_t[i].join();
}
// std::thread t1(forThreads,&sq,1);
// std::thread t2(forThreads,&sq,2);
// std::thread t3(forThreads,&sq,2);
//
// t1.join();
// t2.join();
// t3.join();
return 0;
}
I can't make forEven_class() and forOdd_class() work because of enourmous errors:
If I leave uncommented definition only of forEven/Odd_class functions I get:
error: no matching function for call to ‘myclass::myclass(const myclass&)’
So it seems shared ptr attempts to call copy constructor
And if I uncomment everything I get the whole:
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:42:0,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional: In instantiation of ‘struct std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86: required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1695:9: error: no type named ‘type’ in ‘class std::result_of<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
_M_invoke(_Index_tuple<_Indices...>)
^
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:38:0,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘struct std::_Head_base<2ul, myclass, false>’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:231:12: recursively required from ‘struct std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:231:12: required from ‘struct std::_Tuple_impl<0ul, void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:390:11: required from ‘class std::tuple<void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1703:39: required from ‘struct std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86: required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:137:17: error: ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const std::_Head_base<_Idx, _Head, false>&) [with long unsigned int _Idx = 2ul; _Head = myclass]’ declared to take const reference, but implicit declaration would take non-const
constexpr _Head_base(const _Head_base&) = default;
^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(_UHead&&) [with _UHead = myclass; long unsigned int _Idx = 2ul; _Head = myclass]’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:273:42: required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 2ul; _Head = myclass; _Tail = {}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:900:43: required by substitution of ‘template<class _Tp, class _Arg, class> static std::true_type std::__do_is_direct_constructible_impl::__test(int) [with _Tp = std::_Tuple_impl<2ul, myclass>; _Arg = std::_Tuple_impl<2ul, myclass>&&; <template-parameter-1-3> = <missing>]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:912:43: required from ‘struct std::__is_direct_constructible_impl<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:134:12: required from ‘struct std::__and_<std::is_destructible<std::_Tuple_impl<2ul, myclass> >, std::__is_direct_constructible_impl<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&> >’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:916:12: required from ‘struct std::__is_direct_constructible_new_safe<std::_Tuple_impl<2ul, myclass>, std::_Tuple_impl<2ul, myclass>&&>’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:994:12: [ skipping 21 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:1175:12: required from ‘struct std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass> >’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/type_traits:134:12: required from ‘struct std::__and_<std::is_nothrow_move_constructible<void (*)(SafeQueue<myclass>*, myclass&)>, std::is_nothrow_move_constructible<std::_Tuple_impl<1ul, SafeQueue<myclass>*, myclass> > >’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:269:7: required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx, _Head, _Tail ...>&&) [with long unsigned int _Idx = 0ul; _Head = void (*)(SafeQueue<myclass>*, myclass&); _Tail = {SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1727:41: required from ‘typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86: required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:142:42: error: no matching function for call to ‘myclass::myclass(myclass)’
: _M_head_impl(std::forward<_UHead>(__h)) { }
^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:142:42: note: candidates are:
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
myclass(int val):val(val){
^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: no known conversion for argument 1 from ‘myclass’ to ‘int’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
myclass(myclass &obj){
^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: no known conversion for argument 1 from ‘myclass’ to ‘myclass&’
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/mutex:38:0,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/condition_variable:39,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:9,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:2:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx, _Head, false>::_Head_base(const _Head&) [with long unsigned int _Idx = 2ul; _Head = myclass]’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:257:44: recursively required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 1ul; _Head = SafeQueue<myclass>*; _Tail = {myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:257:44: required from ‘constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl(const _Head&, const _Tail& ...) [with long unsigned int _Idx = 0ul; _Head = void (*)(SafeQueue<myclass>*, myclass&); _Tail = {SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:400:33: required from ‘constexpr std::tuple< <template-parameter-1-1> >::tuple(const _Elements& ...) [with _Elements = {void (*)(SafeQueue<myclass>*, myclass&), SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1678:74: required from ‘std::_Bind_simple<_Callable(_Args ...)>::_Bind_simple(_Callable&&, _Args2&& ...) [with _Args2 = {SafeQueue<myclass>*, myclass}; <template-parameter-2-2> = void; _Callable = void (*)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/functional:1727:41: required from ‘typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type std::__bind_simple(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}; typename std::_Bind_simple_helper<_Func, _BoundArgs>::__type = std::_Bind_simple<void (*(SafeQueue<myclass>*, myclass))(SafeQueue<myclass>*, myclass&)>]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(SafeQueue<myclass>*, myclass&); _Args = {SafeQueue<myclass>*, myclass}]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:116:86: required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:135:25: error: no matching function for call to ‘myclass::myclass(const myclass&)’
: _M_head_impl(__h) { }
^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/tuple:135:25: note: candidates are:
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
myclass(int val):val(val){
^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: no known conversion for argument 1 from ‘const myclass’ to ‘int’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
myclass(myclass &obj){
^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’
In file included from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/x86_64-redhat-linux/bits/c++allocator.h:33:0,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/allocator.h:46,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/string:41,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/locale_classes.h:40,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/ios_base.h:41,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ios:42,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ostream:38,
from /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/iostream:39,
from /gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:1:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = myclass; _Args = {const myclass&}; _Tp = myclass]’:
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_deque.h:1403:6: required from ‘void std::deque<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = myclass; _Alloc = std::allocator<myclass>; std::deque<_Tp, _Alloc>::value_type = myclass]’
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/stl_queue.h:216:9: required from ‘void std::queue<_Tp, _Sequence>::push(const value_type&) [with _Tp = myclass; _Sequence = std::deque<myclass, std::allocator<myclass> >; std::queue<_Tp, _Sequence>::value_type = myclass]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/safeQueue.h:37:9: required from ‘void SafeQueue<T>::push(std::shared_ptr<_Tp1>) [with T = myclass]’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:69:43: required from here
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120:4: error: no matching function for call to ‘myclass::myclass(const myclass&)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
/opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120:4: note: candidates are:
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: myclass::myclass(int)
myclass(int val):val(val){
^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:32:5: note: no known conversion for argument 1 from ‘const myclass’ to ‘int’
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: myclass::myclass(myclass&)
myclass(myclass &obj){
^
/gpfs/home/ichernovalov/Sharamet/Threads 1 2 5 6/5 safeQueue/main.cpp:29:5: note: no known conversion for argument 1 from ‘const myclass’ to ‘myclass&’
So I don't know how to use shared_ptr at all. (especially passing it to thread)
I might have got the lecturer wrong. So what would you recommend to use: unque_ptr or what?
Remove your unnecessary constructors and destructors and change functions forEven_class and forOdd_class and your code will compile again.
Why removing constructors? Because compiler has rules how to generate default constructors. In your case you wanted move constructor generated, but by defining copy constructor and destructor, you prevented compiler from doing so. Your options are:
properly define all constructors including move constructor
remove copy constructor and destructor as I suggested since they doesn't do anything execpt debut output
instruct compiler to generate default move constructor myclass(myclass &&obj) = default
See this SO on automatic generation of move operations
I you want those debug messages, then you have to define those constructors properly. Including task they have to do other than your debug messages.
Regarding changes in functions forEven_class you can´t take the myclass by reference because it is not an lvalue. For more info on this google rvalue reference.
I've come across a strange compiler error while using std::vector::emplace() and std::vector::emplace_back():
#include <vector>
struct Foo {
int bar;
Foo(int _bar) : bar(_bar) { }
};
int main() {
// Declaration 1
std::vector<Foo> vec(10);
// Declaration 2
// std::vector<Foo> vec{};
vec.emplace_back(1);
return 0;
}
When I compile this, I get the following error:
In file included from /usr/include/c++/6/vector:62:0,
from prog.cpp:2:
/usr/include/c++/6/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Foo; _Args = {}]’:
/usr/include/c++/6/bits/stl_uninitialized.h:519:18: required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Foo*; _Size = long unsigned int; bool _TrivialValueType = false]’
/usr/include/c++/6/bits/stl_uninitialized.h:575:20: required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Foo*; _Size = long unsigned int]’
/usr/include/c++/6/bits/stl_uninitialized.h:637:44: required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = Foo*; _Size = long unsigned int; _Tp = Foo]’
/usr/include/c++/6/bits/stl_vector.h:1309:36: required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/6/bits/stl_vector.h:281:30: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<Foo>]’
prog.cpp:11:25: required from here
/usr/include/c++/6/bits/stl_construct.h:75:7: error: no matching function for call to ‘Foo::Foo()’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cpp:7:2: note: candidate: Foo::Foo(int)
Foo(int _bar) : bar(_bar) { }
^~~
prog.cpp:7:2: note: candidate expects 1 argument, 0 provided
prog.cpp:4:8: note: candidate: constexpr Foo::Foo(const Foo&)
struct Foo {
^~~
prog.cpp:4:8: note: candidate expects 1 argument, 0 provided
prog.cpp:4:8: note: candidate: constexpr Foo::Foo(Foo&&)
prog.cpp:4:8: note: candidate expects 1 argument, 0 provided
However, if I comment out declaration 1 and use declaration 2 instead, the code compiles fine. What's going on here?
Your problem is not with vec.emplace_back(1);. Your getting the compilation error because of std::vector<Foo> vec(10);. That line is trying to create a vector with 10 default constructed elements. Since your class does not have a default constructor you cannot create the 10 default elements.
To get it to work you need to provide a instance of the class it can copy into the vector. That would look like
std::vector<Foo> vec(10, Foo(whatever_number_you_want));
Or you could just add a default constructor.
std::vector<Foo> vec{}; does not give you any issues because it does not try to default construct any elements. The empty constructor returns a vector of size 0 meaning no objects were constructed thus avoiding your not defined default constructor.
The reason is that std::vector<Foo> vec(10) will instantiate a vector with 10 "empty" Foo-objects, i.e. instances of class Foo for which the default constructor needs to be called. Your class Foo, however, does not provide a default constructor.
The second statement std::vector<Foo> vec{} instantiates an empty vector, so no Foo-object is instantiated (which would have required a default constructor).
To solve your problem, define a default constructor in Foo:
struct Foo {
int bar;
Foo() : bar(0) {};
Foo(int _bar) : bar(_bar) { };
};
I've been looking around for a way to do this, and I'm not sure it's even possible. I've got a class in Java that takes an instance of a generically-typed interface as part of its constructor, and I'd like to recreate it in C++ (it's a utility class that is handy in many situations). To the best of my understanding, the closest equivalent to an interface in C++ is a pure virtual class, and the (somewhat) equivalent of generics is templates.
So let's say I have some classes defined as follows:
template<typename R>
class AnInterface
{
public:
virtual R run() = 0;
virtual ~AnInterface() {}
};
template<typename R>
class Processor
{
public:
Processor(std::vector<AnInterface<R>> toRun) : toRun(toRun) {}
std::vector<R> process() {
std::vector<R> res;
for(int i = 0; i < this->toRun.size(); ++i)
res.push_back(toRun[i].run());
return res;
}
private:
std::vector<AnInterface<R>> toRun;
};
class AnInstanceClass : public AnInterface<int>
{
int run() { return 1+1; }
};
I'd like to be able to do something like this with them:
int main()
{
std::vector<AnInterface<int>> toRun;
toRun.push_back(AnInstanceClass());
toRun.push_back(AnInstanceClass());
Processor<int> p(toRun);
std::vector<int> p.process();
}
Basically, have a class who's job is to take a list of objects, run them, and then return a list of their results, while being agnostic to the types of objects and results (assuming that the objects have a 'run' function). In Java, I accomplished this with generics and interfaces. I tried implementing the above solution in C++, but it doesn't compile and the compiler output is very cryptic, suggesting that I'm screwing up something very fundamental to the language. My C++ is a little rusty, so I'm not exactly sure what that is. How can something like this be implemented in C++?
Edit: Here's the error message when I try to compile the above code:
In file included from /usr/include/c++/4.8/vector:64:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_vector.h: In instantiation of ‘class std::vector<AnInterface<int> >’:
test.cpp:36:36: required from here
/usr/include/c++/4.8/bits/stl_vector.h:704:7: error: cannot allocate an object of abstract type ‘AnInterface<int>’
resize(size_type __new_size, value_type __x = value_type())
^
test.cpp:4:7: note: because the following virtual functions are pure within ‘AnInterface<int>’:
class AnInterface
^
test.cpp:7:19: note: R AnInterface<R>::run() [with R = int]
virtual R run() = 0;
^
test.cpp: In function ‘int main()’:
test.cpp:40:23: error: expected initializer before ‘.’ token
std::vector<int> p.process();
^
test.cpp: In instantiation of ‘Processor<R>::Processor(std::vector<AnInterface<R> >) [with R = int]’:
test.cpp:39:27: required from here
test.cpp:15:68: error: no matching function for call to ‘std::vector<int, std::allocator<int> >::vector(std::vector<AnInterface<int> >&)’
Processor(std::vector<AnInterface<R> > toRun) : toRun(toRun) {}
^
test.cpp:15:68: note: candidates are:
In file included from /usr/include/c++/4.8/vector:64:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_vector.h:398:9: note: template<class _InputIterator> std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&)
vector(_InputIterator __first, _InputIterator __last,
^
/usr/include/c++/4.8/bits/stl_vector.h:398:9: note: template argument deduction/substitution failed:
test.cpp:15:68: note: candidate expects 3 arguments, 1 provided
Processor(std::vector<AnInterface<R> > toRun) : toRun(toRun) {}
^
In file included from /usr/include/c++/4.8/vector:64:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_vector.h:310:7: note: std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = int; _Alloc = std::allocator<int>]
vector(const vector& __x)
^
/usr/include/c++/4.8/bits/stl_vector.h:310:7: note: no known conversion for argument 1 from ‘std::vector<AnInterface<int> >’ to ‘const std::vector<int, std::allocator<int> >&’
/usr/include/c++/4.8/bits/stl_vector.h:295:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
vector(size_type __n, const value_type& __value = value_type(),
^
/usr/include/c++/4.8/bits/stl_vector.h:295:7: note: no known conversion for argument 1 from ‘std::vector<AnInterface<int> >’ to ‘std::vector<int, std::allocator<int> >::size_type {aka long unsigned int}’
/usr/include/c++/4.8/bits/stl_vector.h:256:7: note: std::vector<_Tp, _Alloc>::vector(const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
vector(const allocator_type& __a)
^
/usr/include/c++/4.8/bits/stl_vector.h:256:7: note: no known conversion for argument 1 from ‘std::vector<AnInterface<int> >’ to ‘const allocator_type& {aka const std::allocator<int>&}’
/usr/include/c++/4.8/bits/stl_vector.h:248:7: note: std::vector<_Tp, _Alloc>::vector() [with _Tp = int; _Alloc = std::allocator<int>]
vector()
^
/usr/include/c++/4.8/bits/stl_vector.h:248:7: note: candidate expects 0 arguments, 1 provided
In file included from /usr/include/c++/4.8/vector:69:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/vector.tcc: In instantiation of ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = AnInterface<int>; _Alloc = std::allocator<AnInterface<int> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<AnInterface<int>*, std::vector<AnInterface<int> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = AnInterface<int>*]’:
/usr/include/c++/4.8/bits/stl_vector.h:913:28: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = AnInterface<int>; _Alloc = std::allocator<AnInterface<int> >; std::vector<_Tp, _Alloc>::value_type = AnInterface<int>]’
test.cpp:37:38: required from here
/usr/include/c++/4.8/bits/vector.tcc:329:19: error: cannot allocate an object of abstract type ‘AnInterface<int>’
_Tp __x_copy = __x;
^
test.cpp:4:7: note: since type ‘AnInterface<int>’ has pure virtual functions
class AnInterface
^
In file included from /usr/include/c++/4.8/vector:69:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/vector.tcc:329:8: error: cannot declare variable ‘__x_copy’ to be of abstract type ‘AnInterface<int>’
_Tp __x_copy = __x;
^
test.cpp:4:7: note: since type ‘AnInterface<int>’ has pure virtual functions
class AnInterface
^
In file included from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33:0,
from /usr/include/c++/4.8/bits/allocator.h:46,
from /usr/include/c++/4.8/vector:61,
from test.cpp:1:
/usr/include/c++/4.8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(__gnu_cxx::new_allocator<_Tp>::pointer, const _Tp&) [with _Tp = AnInterface<int>; __gnu_cxx::new_allocator<_Tp>::pointer = AnInterface<int>*]’:
/usr/include/c++/4.8/ext/alloc_traits.h:216:9: required from ‘static void __gnu_cxx::__alloc_traits<_Alloc>::construct(_Alloc&, __gnu_cxx::__alloc_traits<_Alloc>::pointer, const _Tp&) [with _Tp = AnInterface<int>; _Alloc = std::allocator<AnInterface<int> >; __gnu_cxx::__alloc_traits<_Alloc>::pointer = AnInterface<int>*]’
/usr/include/c++/4.8/bits/stl_vector.h:906:34: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = AnInterface<int>; _Alloc = std::allocator<AnInterface<int> >; std::vector<_Tp, _Alloc>::value_type = AnInterface<int>]’
test.cpp:37:38: required from here
/usr/include/c++/4.8/ext/new_allocator.h:130:9: error: cannot allocate an object of abstract type ‘AnInterface<int>’
{ ::new((void *)__p) _Tp(__val); }
^
test.cpp:4:7: note: since type ‘AnInterface<int>’ has pure virtual functions
class AnInterface
^
In file included from /usr/include/c++/4.8/vector:62:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, const _T2&) [with _T1 = AnInterface<int>; _T2 = AnInterface<int>]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const AnInterface<int>*, std::vector<AnInterface<int> > >; _ForwardIterator = AnInterface<int>*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const AnInterface<int>*, std::vector<AnInterface<int> > >; _ForwardIterator = AnInterface<int>*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const AnInterface<int>*, std::vector<AnInterface<int> > >; _ForwardIterator = AnInterface<int>*; _Tp = AnInterface<int>]’
/usr/include/c++/4.8/bits/stl_vector.h:316:32: required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = AnInterface<int>; _Alloc = std::allocator<AnInterface<int> >]’
test.cpp:39:27: required from here
/usr/include/c++/4.8/bits/stl_construct.h:83:7: error: cannot allocate an object of abstract type ‘AnInterface<int>’
::new(static_cast<void*>(__p)) _T1(__value);
^
test.cpp:4:7: note: since type ‘AnInterface<int>’ has pure virtual functions
class AnInterface
You're basically (attempting to) re-create the functionality of std::generate. The difference is that generate doesn't rely on the somewhat clunky convention of a member function named run. Rather, it invokes something like a function (though it may, and often will, be an overloaded operator()).
We can also (frequently) avoid the separate definition of what you've named AnInstanceClass by defining the class in a lambda expression.
So, in this case, we'd be looking at something like:
std::vector<int> p;
std::generate_n(std::back_inserter(p), 2, [] { return 1 + 1; });
This is basically threading-agnostic, so if you want to run the individual tasks in separate threads, you can do that pretty easily as well. There are some caveats with std::async, but they're pretty much the same regardless of whether you involve std::generate.
Note that this is slightly different from #Severin's answer--he's mentioning std::transform instead of std::generate. The basic difference between the two is that transform takes a set of inputs, transforms them, and produces a set of those outputs. Your AnInstance::run just produces outputs (without taking any inputs) so at least to me it seems like std::generate is a better fit.
std::transform would be more useful if you had something like this:
std::vector<int> inputs { 1, 2, 3, 4, 5};
std::vector<int> results;
std::transform(inputs.begin(), inputs.end(), [](int in) { return in * 2; });
This should produce results of 2, 4, 6, 8, 10.
The only conceptual error you have is trying to get polymorphic behaviour when invoking virtual functions through objects, as opposed to pointers or references to said objects. In C++, to get run-time polymorphism, you need to work with pointers or references. Thus, Processor should work with a std::vector<AnInterface<R>*> like this:
template<typename R>
class Processor
{
public:
Processor(std::vector<AnInterface<R>*> toRun) : toRun(toRun) {}
std::vector<R> process() {
std::vector<R> res;
for(int i = 0; i < this->toRun.size(); ++i)
res.push_back(toRun[i]->run());
return res;
}
private:
std::vector<AnInterface<R>*> toRun;
};
Here's a fixed version of your code.
Another thing to note : when using overriding a virtual function in a derived class, mark the override with the eponymous keyword. This helps the compiler help you.
Do you really need Processor class? What I would propose to use std::transform
std::transform applies the given function to a range and stores the result in another range
vector<AnInterface<R>> does not work because it causes slicing. This is also the cause of your error messages, because some vector operations require to default-construct or copy-construct objects and that is not possible with an abstract class.
Probably vector<shared_ptr<AnInterface<R>>> best matches your intent. shared_ptr is the closest thing C++ has to a Java object reference.
Here is working code in C++11 based on your sample code. One point I would have is that Processor currently takes its vector by value. It could take this by reference, or even by moving, if that better matched your design.
#include <iostream>
#include <memory>
#include <vector>
template<typename R>
struct AnInterface
{
virtual R run() = 0;
virtual ~AnInterface() {}
};
template<typename R>
using AnInterfaceVector = std::vector< std::shared_ptr<AnInterface<R>> >;
template<typename R>
class Processor
{
public:
Processor(AnInterfaceVector<R> toRun) : toRun(toRun) {}
std::vector<R> process()
{
std::vector<R> res;
for (auto && r : toRun)
res.push_back( r->run() );
return res;
}
private:
AnInterfaceVector<R> toRun;
};
struct AnInstanceClass : AnInterface<int>
{
int run() override { return temp; }
AnInstanceClass(int n): temp(n) {}
int temp;
};
int main()
{
AnInterfaceVector<int> toRun;
toRun.emplace_back( std::make_shared<AnInstanceClass>(4) );
toRun.emplace_back( std::make_shared<AnInstanceClass>(7) );
Processor<int> p{toRun};
auto results = p.process();
for (auto && i : results)
std::cout << i << " ";
std::cout << std::endl;
}
NB. I don't offer any claim whether this is better or worse than using a different pattern as other answers have suggested; this is just a working version of the code you were trying to write.
As was already mentioned in the other answers, your error was trying to use a vector of interfaces (std::vector<AnInterface<int>>) instead of a vector of pointers to interfaces like std::vector<AnInterface<int>*> - with only the latter allowing polymorphism, whereas your version would try to store actual Interface objects (which is of course not posssible as they are abstract classes).
I wanted to mention in addition, that there is a nice pattern by Sean Parent that makes it unnecessary for your AnInstanceClass to inhereit from anything, as long as it implements a member function with the correct name and signature. This is quite handy, because you can e.g. even use lambdas or plain functions (after wrapping them in a std::function) which cannot inherit from anything:
#include <vector>
#include <memory>
#include <iostream>
#include <algorithm>
#include <functional>
//R is the return type
template<class R>
class Processor {
public:
//T can be anything, that has an ()-operator
template<class T>
void push_back(const T& arg) {
todo.emplace_back(std::make_unique<runnable_imp<T>>(arg));
}
std::vector<R> process() {
std::vector<R> ret;
for (auto& e : todo) {
ret.push_back(e->run());
}
return ret;
}
private:
struct runnable_concept {
virtual R run()=0;
virtual ~runnable_concept(){};
};
template<class T>
struct runnable_imp :public runnable_concept {
runnable_imp(T data) :data(data){};
virtual R run() override { return data(); }
T data;
};
std::vector<std::unique_ptr<runnable_concept>> todo;
};
struct SomeClass {
SomeClass(int arg) :arg(arg){};
int operator()(){ return arg; }
int arg;
};
int SomeFunction(){ return 30; }
int main()
{
Processor<int> pr;
pr.push_back([]{return 10; });
pr.push_back(SomeClass(20));
pr.push_back(std::function<int()>(SomeFunction));
std::vector<int> res= pr.process();
for (auto e : res) {
std::cout << e << std::endl;
}
}
class Foo {
vector<Bar> bars;
public:
Foo(int barcount) : { bars(barcount, 0); };
};
I'm trying to turn the bars vector into a vector holding barcount Bars. However I get 2 errors when doing this:
Foo.cpp:8: error: expected identifier before ‘{’ token
Foo(int barcount) : { bars(barcount, 0); };
^
Foo.cpp:8: error: no match for call to ‘(std::vector<Bar>) (int&, int)’
Foo(int barcount) : { bars(barcount, 0); };
Any help on what might be going wrong would be much appreciated.
EDIT: This is my code now (Foo/Bar replaced):
class Machine {
vector<Rotor> rotors;
public:
Machine(int rotorcount) : rotors(rotorcount, 0) {}
};
And I get a pretty long error message:
/usr/include/c++/4.8/bits/stl_vector.h: In instantiation of ‘void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_Integer, _Integer, std::__true_type) [with _Integer = int; _Tp = Rotor; _Alloc = std::allocator<Rotor>]’:
/usr/include/c++/4.8/bits/stl_vector.h:404:55: required from ‘std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = int; _Tp = Rotor; _Alloc = std::allocator<Rotor>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<Rotor>]’
Machine.cpp:8:51: required from here
/usr/include/c++/4.8/bits/stl_vector.h:1166:59: error: no matching function for call to ‘std::vector<Rotor>::_M_fill_initialize(std::vector<Rotor>::size_type, int&)’
_M_fill_initialize(static_cast<size_type>(__n), __value);
^
/usr/include/c++/4.8/bits/stl_vector.h:1166:59: note: candidate is:
/usr/include/c++/4.8/bits/stl_vector.h:1212:7: note: void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = Rotor; _Alloc = std::allocator<Rotor>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = Rotor]
_M_fill_initialize(size_type __n, const value_type& __value)
^
/usr/include/c++/4.8/bits/stl_vector.h:1212:7: note: no known conversion for argument 2 from ‘int’ to ‘const value_type& {aka const Rotor&}’
The initializer list goes after the comma, but before the constructor body, and is not followed by a semicolon:
Foo(int barcount) : bars(barcount, 0) {};
no known conversion for argument 2 from ‘int’ to ‘const value_type& {aka const Rotor&}’
Sounds like you don't have a constructor that takes int as a single parameter.