std::move doe's not compile when moving an std::packaged_task<void()> object.
the errors are:
error C2182: '_Get_value' : illegal use of type 'void'
error C2182: '_Val' : illegal use of type 'void'
error C2182: '_Val' : illegal use of type 'void'
error C2665: 'std::forward': none of the 2 overloads could convert all the argument types
error C2512: 'std::_Promise': no appropriate default constructor available
The code is:
struct CalcFib
{
int m_num;
int m_res;
CalcFib(int number) :m_num(number)
{
}
CalcFib() :m_num(0)
{
}
void operator()()
{
m_res = fib(m_num);
}
int fib(int num)
{
if (num < 2) return num;
else return fib(num - 1) + fib(num - 2);
}
};
std::packaged_task<void()> task(std::move(CalcFib(30)));
std::packaged_task<void()> task1 = std::move(task);
This code is successfully compiled:
struct CalcFib
{
int m_num;
int m_res;
CalcFib(int number) :m_num(number)
{
}
CalcFib() :m_num(0)
{
}
int operator()()
{
m_res = fib(m_num);
return m_res;
}
int fib(int num)
{
if (num < 2) return num;
else return fib(num - 1) + fib(num - 2);
}
};
std::packaged_task<int()> task(std::move(CalcFib(30)));
std::packaged_task<int()> task1 = std::move(task);
similar issue was asked here but has not answer
This is visual studio compiler bug, I found a nice solution by implementing packaged_task here
Related
I am studying C++ on Essential C++ by lippman. Here is some code where two lines contain error while I don't know why it's happening and how to fix it.
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
const vector<int>* fibon_seq(int size) {
const int max_size = 1024;
static vector<int> elems;
if (size <= 0 || size > max_size) {
cerr << "Error";
return 0;
}
for (int ix = elems.size(); ix < size; ++ix) {
if (ix == 0 || ix == 1)
elems.push_back(1);
else elems.push_back(elems[ix - 1] + elems[ix - 2]);
}
return &elems;
}
void display(const vector<int>* vec, ostream &os = cout) {
if (!vec)
cerr << "null vector";
for (int i = 0; i < (vec)->size(); ++i)
os << (*vec)[i] << " ";
os << endl;
}
bool fibon_elem(int pos, int &elem, const vector<int>* (*seq_ptr)(int)) {
const vector<int> *pseq = seq_ptr(pos);
if (!pseq){
elem = 0; return false;
}
elem = (*pseq)[pos - 1];
return true;
}
int main()
{
const vector<int>* (*(*seq_array)[1])(int);
(*seq_array)[0] = fibon_seq;
vector<int>* (*seq_ptr)(int);
int seq_index = 0;
seq_ptr = (*seq_array)[0];//This is the line with error.
//(a value of type "const std::vector<int, std::allocator<int>> *(*)(int)"
//cannot be assigned to an entity of type "std::vector<int, std::allocator<int>>
//*(*)(int)"
//C2440 '=': cannot convert from 'const std::vector<int,std::allocator<_Ty>>
//*(__cdecl *)(int)' to 'std::vector<int,std::allocator<_Ty>>
//*(__cdecl *)(int)'
int a;
fibon_elem(12, a, seq_ptr);//This is the line with error.
//argument of type "std::vector<int, std::allocator<int>> *(*)(int)"
//is incompatible with parameter of type "const std::vector<int, std::allocator<int>>
//*(*)(int)"
//C2664 'bool fibon_elem(int,int &,const std::vector<int,std::allocator<_Ty>>
//*(__cdecl *)(int))': cannot convert argument 3 from 'std::vector<int,std::allocator<_Ty>>
//*(__cdecl *)(int)' to 'const std::vector<int,std::allocator<_Ty>>
//*(__cdecl *)(int)' test
getchar();
return 0;
}
For the first line in error, I make both sides of the equation the same type, while the compiler says that the value cannot be assigned. For the second line in error, the two same type are incompatible with each other.
And the error message given by compiler is the following:
Your function fibon_seq returns a const vector<int>*, and you're trying to assign it to a vector<int>* which is seq_ptr. Change seq_ptr to a const vector<int>* or change the return type of fiber_seq.
I am getting an error and I don't know how to fix it. I checked everything and maybe I overlooked something, but I am not able to find the problem.
Errors:
1>------ Build started: Project: Aquarium, Configuration: Release x64 ------
1> Fish.cpp
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(21): error C2065: 'Fish': undeclared identifier
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(21): error C2059: syntax error: '>'
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(21): error C2976: 'std::vector': too few template arguments
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(682): note: see declaration of 'std::vector'
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(24): error C2061: syntax error: identifier 'Fish'
1> LooseCalculationClass.cpp
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(21): error C2065: 'Fish': undeclared identifier
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(21): error C2059: syntax error: '>'
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(21): error C2976: 'std::vector': too few template arguments
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(682): note: see declaration of 'std::vector'
1>c:\users\lloyd17\dropbox\aquarium project\aquarium\aquarium\EntityControl.h(24): error C2061: syntax error: identifier 'Fish'
1>LooseCalculationClass.cpp(7): warning C4551: function call missing argument list
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Fish.h
#pragma once
#include <iostream>
#include <string>
#include "EntityControl.h"
class Fish
{
private:
//location of the fish
unsigned int _xLocation = 0, _yLocation = 0, _zLocation = 0;
//name of fish
std::string nameOfFish;
unsigned int speed;
public:
//constructor
Fish(std::string name, unsigned int fishSpeed)
{
nameOfFish = name;
speed = fishSpeed;
}
//getters
int getX() const;
int getY() const;
int getZ() const;
std::string getName() const;
void changeX(unsigned int x);
void changeY(unsigned int y);
void changeZ(unsigned int z);
void move();
~Fish();
};
Fish.cpp
#include "Fish.h"
int Fish::getX() const
{
return _xLocation;
}
int Fish::getY() const
{
return _yLocation;
}
int Fish::getZ() const
{
return _zLocation;
}
std::string Fish::getName() const
{
return nameOfFish;
}
void Fish::changeX(unsigned int x)
{
_xLocation = x;
}
void Fish::changeY(unsigned int y)
{
_yLocation = y;
}
void Fish::changeZ(unsigned int z)
{
_zLocation = z;
}
void Fish::move()
{
EntityControl entity;
unsigned int x = rand() % entity.getXContainer();
unsigned int y = rand() % entity.getYContainer();
unsigned int z = rand() % entity.getZContainer();
}
Fish::~Fish()
{
}
Aquarium.cpp(Main)
using namespace std;
#include "EntityControl.h"
#include <Windows.h>
#include <time.h>
#include "LooseCalculationClass.h"
#include <thread>
#include "Fish.h"
int main() {
/*Not using new in object definitions so I don't have to delete them afterwards since pointers don't stay in memory*/
bool running = true;
//defining my objects for functions
EntityControl entity;
LooseCalculationClass calc;
vector<Fish*> fishVector;
Fish a("Lloyd", 200);
fishVector.push_back(&a);
std::thread t1(&EntityControl::movementController, entity, &fishVector);
//std::thread t2(&LooseCalculationClass::userInput, calc);
//t2.detach();
t1.detach();
//main gameloop, prints out the results for every fish, waits a bit and then refreshes the screen
while(running){
for (auto Fish_ptr : fishVector) {
calc.printOutXYZ(*Fish_ptr);
Sleep(500000);
system("pause");
//system("cls");
}
}
return 0;
}
EntityControl.h
#pragma once
#include <iostream>
#include <vector>
#include "Fish.h"
#include <random>
#include <array>
#include <Windows.h>
class EntityControl
{
private:
/*Didn't make a separate object because I only
needed the x,y,z of the fish container although it is against the rules of object oriented programming*/
const unsigned int _xContainer = 20;
const unsigned int _yContainer = 60;
const unsigned int _zContainer = 40;
public:
/*grabs the location of a vector of fish pointers, then takes the
vector and accesses every object threw it's data location with dereferencing.
(Controls the movement of the fish and prevents collision)*/
void movementController(std::vector<Fish*> *fishInputVector);//thread!!
//ACHTUNG! fishInput is the fish to check the surrounding of, changing this might bring up unexpected errors
bool CheckCollision(Fish* fishInput , Fish* fishInput2);
int getXContainer() const;
int getYContainer() const;
int getZContainer() const;
~EntityControl();
};
EntityControl.cpp
#include "EntityControl.h"
/*if the container was much larger,
then multiple threads would be a better solution*/
void EntityControl::movementController(std::vector<Fish*> * fishInputVector)
{
while (true) {
for (auto fish_ptr : *fishInputVector) {
}
}
}
bool EntityControl::CheckCollision(Fish * fishInput, Fish * fishInput2)
{
//collision true/false
bool collision = false;
//collision detectors
bool xCollision = false;
bool yCollision = false;
bool zCollision = false;
//fishInput
unsigned int xOriginal = fishInput->getX();
unsigned int yOriginal = fishInput->getY();
unsigned int zOriginal = fishInput->getZ();
//fishInput2
unsigned int xEntity = fishInput2->getX();
unsigned int yEntity = fishInput2->getY();
unsigned int zEntity = fishInput2->getZ();
//directions, (triggerBox)
if (xOriginal - 1 == xEntity || xOriginal + 1 == xEntity || xOriginal == xEntity) { xCollision = true; }
if (yOriginal - 1 == yEntity || yOriginal + 1 == yEntity || yOriginal == yEntity) { yCollision = true; }
if (zOriginal - 1 == zEntity || zOriginal + 1 == zEntity || zOriginal == zEntity) { zCollision = true; }
//returns true if all 3 directions are true
if (xCollision && yCollision && zCollision) { collision = true; }
return collision;
}
int EntityControl::getYContainer() const
{
return _yContainer;
}
int EntityControl::getXContainer() const
{
return _xContainer;
}
int EntityControl::getZContainer() const
{
return _xContainer;
}
EntityControl::~EntityControl()
{
}
It worked before, don't know exactly what has changed. I think everything is declared like it should but this has been bothering me for a while. Putting the classes in another project and running it from there didn't work either. Neither did changing around some variables / removing methods, but again, I might have missed something.
The problem is that when you include EntityControl.h you have also included Fish.h which refers to Fish defined in Fish.h. However EntityControl.h refers to Fish.h which won't get included because of the pragma once directive. If you remove pragma once then you'd get an infinite loop because of circular dependency.
To solve the problem of circular dependencies use forward declarations.
Remove #include "EntityControl.h" from Fish.h and write class EntityControl; instead.
You may also remove #include "Fish.h"; from EntityControl.h and write class Fish; in its stead.
I'm trying to sort a list of a custom struct type, with a custom function I have write, but give me an error:
Use of undeclared identifier
struct myStruct
{
int x1;
int x2;
};
bool CompareData(const myStruct& a, const myStruct& b)
{
if (a.x1 < b.x1) return true;
if (b.x1 < a.x1) return false;
// a=b for primary condition, go to secondary
if (a.x2 < b.x2) return true;
if (b.x2 < a.x2) return false;
return false;
}
void sortingList ()
{
std::list<myStruct> custom_dist;
//...Fill list
custom_dist.sort(CompareData); //Here i receive the error
}
This is the error:
beacuse seem that expects input parameters...
This code compiles fine for me. Have you included the list from std? This is how I am building it: g++ -Wall main.cpp
#include <list>
struct myStruct
{
int x1;
int x2;
};
bool CompareData(const myStruct& a, const myStruct& b)
{
if (a.x1 < b.x1) return true;
if (b.x1 < a.x1) return false;
// a=b for primary condition, go to secondary
if (a.x2 < b.x2) return true;
if (b.x2 < a.x2) return false;
return false;
}
int main()
{
std::list<myStruct> custom_dist;
custom_dist.sort(CompareData);
return 0;
}
How do you make a type that is compared by reference but enforce that it can't be created in functions (prevent references to stack/deleted objects).
I came up with the Error type below and was proud of it, until I realized you can do "return Error::New(...)" inside a function. The problem is in the h() function.
#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;
class Error {
std::string _str;
const Error &from;
Error();
Error(const char *s)
: _str(s), from(*this)
{
}
public:
Error(const Error &err)
: from(err.from)
{
}
static Error New(const char *s) {
return Error(s);
}
bool operator== (const Error &rhs) const {
return (&from == &rhs.from);
}
bool operator!= (const Error &rhs) const {
return (&from != &rhs.from);
}
std::string ToString() {
return from._str;
}
public:
static const Error None;
};
const Error Error::None("none");
// user errors
auto ErrConnect = Error::New("failed to connect");
auto ErrWrite = Error::New("invalid write");
Error f() {
return ErrConnect;
}
Error g() {
return Error::None;
}
Error h() {
return Error::New("test");
}
int main()
{
printf("ErrConnect == ErrConnect : %d\n", ErrConnect == ErrConnect);
printf("ErrConnect == ErrWrite : %d\n", ErrConnect == ErrWrite);
printf("f() == ErrConnect : %d\n", f() == ErrConnect);
printf("f() == ErrWrite : %d\n", f() == ErrWrite);
printf("f() != ErrConnect : %d\n", f() != ErrConnect);
printf("f() != ErrWrite : %d\n", f() != ErrWrite);
printf("f() == Error::None : %d\n", f() == Error::None);
printf("f() != Error::None : %d\n", f() != Error::None);
printf("g() == Error::None : %d\n", g() == Error::None);
printf("g() != Error::None : %d\n", g() != Error::None);
printf("f().ToString() : %s\n", f().ToString().c_str());
printf("ErrConnect.ToString() : %s\n", ErrConnect.ToString().c_str());
auto err = f();
auto err2 = err;
auto err3 = err2;
printf("err3 == ErrConnect : %d\n", err3 == ErrConnect);
auto err4 = h();
printf("err4 from h() : %s\n", err4.ToString().c_str());
}
Allowing something to be created at global scope, but not in a function, cannot be done.
Keeping track of the original Error& is not required for anything you are doing. Instead, you want the creation of an error to create a unique token, and all Errors copied or moved from it to carry that token with them. That token being Error& this is not required, but the lifetime of that token needs to extend over the lifetime of all Errors copied from the original.
One approach would be to use type tags, possibly macro assisted, to generate your errors. With care, the token can be arranged to be both unique and not require extra work on a per-error basis.
As an example:
struct ErrorToken {
virtual std::string Description() const = 0;
~ErrorToken() {}
};
template<typename T>
struct ErrorTokenImpl:ErrorToken {
virtual std::string Description() const /* final override if C++11 */ {
return T::desc();
}
};
class Error {
ErrorToken* token;
template<typename T>
static ErrorToken* get_token() {
static std::unique_ptr<ErrorToken> retval( new ErrorTokenImpl<T>() );
return retval.get();
}
public:
template<typename T>
Error(): token( get_token<T>() );
bool operator==(Error const& o) const { return token == o.token; } // etc
std::string GetDescription() const {
return token->Description();
}
};
#define MAKE_ERROR(Y, X) Error< struct Y { static const char* desc() { return X; }; } >()
const Error ErrConnect = MAKE_ERROR(Connection, "failed to connect");
now, anyone can create an error in any context, but each creation of the error has a tag and a string, and the created token will last until static object cleanup time.
I've found that the best way to implement this is using a static std::atomic counter (specifically, _uint_fast64_t seems best) from which ids are created for each error type in the Error(const char *s) constructor and std::atomic::fetch_add() to fetch/increment it:
http://en.cppreference.com/w/cpp/atomic/atomic
The only drawback is that these are only present in C++11 (Visual Studio 2012; Linux should not be a problem except for old distros).
I ended up using UUID's:
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
using namespace std;
class Error {
std::string msg;
boost::uuids::uuid tag;
public:
Error(const char *s)
: msg(s), tag(boost::uuids::random_generator()())
{
}
Error(const Error &rhs)
: msg(rhs.msg), tag(rhs.tag)
{
}
Error(Error &&rhs)
: msg(std::move(rhs.msg)), tag(rhs.tag)
{
}
Error &operator=(const Error &rhs) {
msg = rhs.msg;
tag = rhs.tag;
return *this;
}
bool operator==(const Error &rhs) const {
return (tag == rhs.tag);
}
bool operator!=(const Error &rhs) const {
return (tag != rhs.tag);
}
std::string ToString() {
return msg;
}
public:
static const Error None;
};
const Error Error::None("none");
// user errors
auto ErrConnect = Error("failed to connect");
auto ErrWrite = Error("invalid write");
What is the error in this file?
I get:
foo2.cpp:9: error: expected primary-expression before '(' token
foo2.cpp:9: error: expected primary-expression before 'int'
foo2.cpp:9: error: expected ';' before '{' token
int main(void)
{
class X {
int i;
public:
X(int ii = 0);
};
X::X(int ii) { i = ii; }
return 0;
}
First, may I ask, WHY?
Second, you can't provide an implementation inside a method (including main). If you must do this, keep the implementation inline:
int main()
{
class X {
int i;
public:
X(int ii = 0){ i = ii; }
};
return 0;
}
You cannot nest functions in C++. To modify your program, you have two alternatives. You may move your class definition outside of main, or you may put your method definition inside the class:
First alternative:
class X {
int i;
public:
X(int ii = 0);
};
X::X(int ii) { i = ii; }
int main(void)
{
return 0;
}
Second alternative:
int main(void)
{
class X {
int i;
public:
X(int ii = 0) { i = ii; }
};
return 0;
}