template argument was not declared in this scope - c++

Why am I having issues compiling this in g++ 4.8.5, -std=c++11 -O2 -lm?
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <numeric>
#include <sstream>
#include <utility>
template<uint_fast32_t N>
class Jollo
{
private:
template<uint_fast32_t c>
struct Player
{
int_fast32_t cards[c]; // This line is OK!
uint_fast32_t nsize = c; // error 'c' was not declared in this scope
friend std::istream& operator>>(std::istream& is, Player& p)
{
for(auto& i : p.cards){
is >> i;
}
return is;
}
};
private:
enum JP_ID{ JPID_PRINCE = N+1, JPID_PRINCESS, JPID_NONE };
Player<2> m_Prince;
Player<3> m_Princess;
int_fast32_t deck[N];
constexpr static int_fast32_t RoundsToWin {2};
int_fast32_t NextAvailableCard(const JP_ID& idPlayer, int_fast32_t lastPlayedCard = 0);
public:
Jollo<N>(){
static_assert( N>4, "Invalid deck size - JolloManager");
}
bool Read();
int_fast32_t GetWinningCard();
};
template<uint_fast32_t N>
bool Jollo<N>::Read()
{
static std::string line;
std::getline(std::cin, line);
std::istringstream issline(line);
issline >> m_Princess;
issline >> m_Prince;
return (m_Princess.cards[0] != 0);
}
template<uint_fast32_t N>
int_fast32_t Jollo<N>::NextAvailableCard(const JP_ID& idPlayer, int_fast32_t lastPlayedCard)
{
if(idPlayer == JPID_PRINCE)
{
for(int_fast32_t i{0}; i<m_Prince.nsize; ++i) {
if(deck[m_Prince.cards[i] - 1] != JPID_PRINCE){
deck[m_Prince.cards[i] - 1] = JPID_PRINCE;
return m_Prince.cards[i];
}
}
} else
if(idPlayer == JPID_PRINCESS)
{
for(int_fast32_t i{0}; i<m_Princess.nsize; ++i) {
if(deck[m_Princess.cards[i] - 1] != JPID_PRINCESS && deck[m_Princess.cards[i] - 1] > lastPlayedCard) {
deck[m_Princess.cards[i] - 1] = JPID_PRINCESS;
return m_Princess.cards[i];
}
}
//no card was higher, return lowest available card
for(int_fast32_t i{0}; i<m_Princess.nsize; ++i) {
if(deck[m_Princess.cards[i] - 1] != JPID_PRINCESS) {
deck[m_Princess.cards[i] - 1] = JPID_PRINCESS;
return m_Princess.cards[i];
}
}
}
for(uint_fast32_t i{0}; i<N; i++)
{
if(deck[i] != JPID_PRINCE && deck[i] != JPID_PRINCESS && deck[i] > lastPlayedCard ) {
return deck[i];
}
}
return -1;
}
template<uint_fast32_t N>
int_fast32_t Jollo<N>::GetWinningCard()
{
std::iota(deck, deck + N, 1);
std::sort(m_Prince.cards, m_Prince.cards + m_Prince.nsize, std::greater<int_fast32_t>());
std::sort(m_Princess.cards, m_Princess.cards + m_Princess.nsize);
int_fast32_t princeWins {0};
int_fast32_t princessWins {0};
for(int_fast32_t round {0}; round < RoundsToWin; ++round) //play two first rounds
{
int_fast32_t princeCard = NextAvailableCard(JPID_PRINCE);
int_fast32_t princessCard = NextAvailableCard(JPID_PRINCESS, princeCard);
if(princessCard > princeCard){
++princessWins;
} else {
++princeWins;
}
}
int_fast32_t lastPrincessCard = NextAvailableCard(JPID_PRINCESS); //important to flip the last card on the deck before continuing
if(princessWins == RoundsToWin){
return -1;
}
if(princeWins == RoundsToWin){
return NextAvailableCard(JPID_NONE);
}
return NextAvailableCard(JPID_NONE, lastPrincessCard);
}
int main()
{
Jollo<52u> jollo;
while(true)
{
if(!jollo.Read()) {
break;
}
std::cout << jollo.GetWinningCard() << '\n';
}
return 0;
}
I can compile it on almost any other g++ version with c++11 flags.

This would seem to be GCC bug 57887, which seems to have been fixed in 4.9.0. I would suggest updating your compiler to something remotely not ancient…
If you cannot update your compiler for some reason (you really should update your compiler), a workaround would seem to be to avoid the in-class member initializer and use the constructor's initializer list instead:
class Jollo
{
private:
template<int c>
struct Player
{
int cards[c];
int nsize;
Player() : nsize(c) {}
};
};
working example here

Related

Unknown Type Name when using threads

I am trying to find the minimum vertex cover by giving the vertex and edge input in specific format from the user using threads. Here is my code:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cctype>
#include <list>
#include <set>
#include <vector>
#include <climits>
#include <memory>
#include <algorithm>
#include <pthread.h>
#include <unistd.h>
#include "minisat/core/Solver.h"
using namespace std;
static void *AVC2_Vertex_Cover(void *);
void min_vertex_cover_algorithm(Graph &graph_builder){
int ret;
pthread_t AVC2_thread;
ret = pthread_create(&AVC2_thread, NULL, AVC2_Vertex_Cover, &graph_builder);
if(ret)
exit(1);
pthread_join(AVC2_thread, NULL);
pthread_exit(NULL);
}
struct Edge{
unsigned v1,v2;
};
typedef std::vector<unsigned> Vertex_vector;
typedef std::list<unsigned > Vertex_Adjacency_list;
typedef std::vector<Vertex_Adjacency_list> Adjacency_Traversal_list;
struct Graph{
std::size_t no_of_edges;
Adjacency_Traversal_list adjacency_list;
void initialize_graph(unsigned vertices_number);
void construct_edge(Edge edge);
void clear(unsigned vertex);
};
void Graph::initialize_graph(unsigned num){
adjacency_list.clear();
no_of_edges = 0;
adjacency_list.resize(num,{});
}
void Graph::construct_edge(Edge edge) {
auto &literal_1 = adjacency_list[edge.v1];
auto &literal_2 = adjacency_list[edge.v2];
literal_1.push_back(edge.v2);
literal_2.push_back(edge.v1);
no_of_edges ++;
}
void *AVC2_Vertex_Cover(void *input)
{
Graph g = *(const Graph *)input;
unsigned int V = g.adjacency_list.size();
bool visited[V];
for (int i=0; i<V; i++)
visited[i] = false;
for (int u=0; u<V; u++)
{
if (visited[u] == false)
{
for(int x : g.adjacency_list[u])
{
int v = x;
if (visited[v] == false)
{
visited[v] = true;
visited[u] = true;
break;
}
}
}
}
// Print the vertex cover
std::cout << "APPROX-VC-2: ";
for (int i=0; i<V; i++){
if (visited[i])
if(i == V-1)
cout << i << std::endl;
else
cout << i << ",";
}
}
void *IO_thread(void *)
{
Graph &graph_builder = *new Graph();
char character_input;
string my_input;
unsigned int no_of_vertices = 0;
string edge_stream;
char prev_choice = ' ';
while (getline(cin, my_input))
{
istringstream stream_string(my_input);
while (stream_string >> character_input)
{
character_input=(toupper(character_input));
try
{
switch (character_input)
{
case 'V' :
if (prev_choice == 'V')
{
cerr << "Error: V must be followed by E only.\n";
break;
}
else
{
stream_string >> no_of_vertices;
if(no_of_vertices <= 0)
{
throw "Invalid number of vertices";
}
graph_builder.initialize_graph(no_of_vertices);
prev_choice = 'V';
break;
}
case 'E' :
{
unsigned int flag_Entry = 0;
if ( prev_choice == 'E')
{
cerr << "Error: V and E always occur together.\n ";
break;
}
else
{
stream_string >> edge_stream;
istringstream edge_stream_character(edge_stream);
char edg_char;
unsigned int temp = 0;
unsigned int v1;
unsigned int v2;
edge_stream_character >> edg_char;
while (edg_char != '}')
{
edge_stream_character >> edg_char;
if (edg_char == '}')
{
flag_Entry = 1;
break;
}
else
{
edge_stream_character >> temp;
v1 = temp;
edge_stream_character >> edg_char;
edge_stream_character >> temp;
v2 = temp;
edge_stream_character >> edg_char;
edge_stream_character >> edg_char;
if (v1 >= no_of_vertices || v2 >= no_of_vertices)
{
cerr << "Error: Vertex out of range.\n";
graph_builder.adjacency_list.clear();
break;
}
graph_builder.construct_edge({v1,v2});
}
}
if(flag_Entry == 1)
{
prev_choice = 'E';
break;
}
min_vertex_cover_algorithm(graph_builder);
prev_choice = 'E';
break;
}
}
}
}
catch (const char* err)
{
cerr << "Error:" << err << endl;
}
}
}
return 0;
}
int main(int argc, char **argv){
int ret;
pthread_t IO_thread;
ret = pthread_create(&IO_thread, NULL, IO_thread,NULL);
if(ret)
return 1;
pthread_join(IO_thread,NULL);
pthread_exit(NULL);
}
I am getting an error:
unknown type name 'Graph'
void min_vertex_cover_algorithm(Graph &graph_builder){
I am not able to find why this error is occuring. It will be very helpful if I get some solutions.
Just like you, the compiler will read from top to bottom. When it reaches the line:
void min_vertex_cover_algorithm(Graph &graph_builder){
It has to go, ok, lets use a Graph reference. It will look for the declaration of a Graph, which it cannot find, because you have declared (and defined) it below. To solve this, give the compiler a hint. Declare the Graph above the function with:
struct Graph;
void min_vertex_cover_algorithm(Graph &graph_builder){
Or simply move the whole struct definition above the function.

Getting Permutations with Repetitions in this special way

I have a list of {a,b} and i need all possible combinatations where say n=3.
so:
[a,b,a],
[b,a,b]
[a,a,a]
[b,b,b]
etc.
Is there a name of such a problem
My current solution just uses random sampling and is very inefficient:
void set_generator(const vector<int>& vec, int n){
map<string, vector<int>> imap;
int rcount = 0;
while(1){
string ms = "";
vector<int> mset;
for(int i=0; i<n; i++){
int sampled_int = vec[rand() % vec.size()];
ms += std::to_string(sampled_int);
mset.emplace_back(sampled_int);
}
if(rcount > 100)
break;
if(imap.count(ms)){
rcount += 1;
//cout << "*" << endl;
continue;
}
rcount = 0;
imap[ms] = mset;
cout << ms << endl;
}
}
set_generator({1,2},3);
Let us call b the size of the input vector.
The problem consists in generating all numbers from 0 to b^n - 1, in base b.
A simple solution increments the elements of an array one by one, each from 0 to b-1.
This is performed by the function increment in the code hereafter.
Output:
111
211
121
221
112
212
122
222
The code:
#include <iostream>
#include <vector>
#include <string>
#include <map>
void set_generator_op (const std::vector<int>& vec, int n){
std::map<std::string, std::vector<int>> imap;
int rcount = 0;
while(1){
std::string ms = "";
std::vector<int> mset;
for(int i=0; i<n; i++){
int sampled_int = vec[rand() % vec.size()];
ms += std::to_string(sampled_int);
mset.emplace_back(sampled_int);
}
if(rcount > 100)
break;
if(imap.count(ms)){
rcount += 1;
//cout << "*" << endl;
continue;
}
rcount = 0;
imap[ms] = mset;
std::cout << ms << "\n";
}
}
// incrementation of a array of int, in base "base"
// return false if max is already attained
bool increment (std::vector<int>& cpt, int base) {
int n = cpt.size();
for (int i = 0; i < n; ++i) {
cpt[i]++;
if (cpt[i] != base) {
return true;
}
cpt[i] = 0;
}
return false;
}
void set_generator_new (const std::vector<int>& vec, int n){
int base = vec.size();
std::vector<int> cpt (n, 0);
while (true) {
std::string permut = "";
for (auto &k: cpt) {
permut += std::to_string (vec[k]);
}
std::cout << permut << "\n";
if (!increment(cpt, base)) return;
}
}
int main() {
set_generator_op ({1,2},3);
std::cout << "\n";
set_generator_new ({1,2},3);
}
Following advices of Jarod42, I have
suppressed the useless conversion to a string
used a more elegant do ... while instead of the while true
inversed the iterators for printing the result
Moreover, I have created a templated version of the program.
New output:
111
112
121
122
211
212
221
222
aaa
aab
aba
abb
baa
bab
bba
bbb
And the new code:
#include <iostream>
#include <vector>
#include <string>
#include <map>
// incrementation of a array of int, in base "base"
// return false if max is already attained
bool increment (std::vector<int>& cpt, int base) {
int n = cpt.size();
for (int i = 0; i < n; ++i) {
cpt[i]++;
if (cpt[i] != base) {
return true;
}
cpt[i] = 0;
}
return false;
}
template <typename T>
void set_generator_new (const std::vector<T>& vec, int n){
int base = vec.size();
std::vector<int> cpt (n, 0);
do {
for (auto it = cpt.rbegin(); it != cpt.rend(); ++it) {
std::cout << vec[*it];
}
std::cout << "\n";
} while (increment(cpt, base));
}
int main() {
set_generator_new<int> ({1,2}, 3);
std::cout << "\n";
set_generator_new<char> ({'a','b'}, 3);
}
Besides the concrete answer for integer usage, I want to provide a generic way I needed during test case construction for scenarios with a wide spread of various parameter variations. Maybe it's helpful to you too, at least for similar scenarios.
#include <vector>
#include <memory>
class SingleParameterToVaryBase
{
public:
virtual bool varyNext() = 0;
virtual void reset() = 0;
};
template <typename _DataType, typename _ParamVariationContType>
class SingleParameterToVary : public SingleParameterToVaryBase
{
public:
SingleParameterToVary(
_DataType& param,
const _ParamVariationContType& valuesToVary) :
mParameter(param)
, mVariations(valuesToVary)
{
if (mVariations.empty())
throw std::logic_error("Empty variation container for parameter");
reset();
}
// Step to next parameter value, return false if end of value vector is reached
virtual bool varyNext() override
{
++mCurrentIt;
const bool finished = mCurrentIt == mVariations.cend();
if (finished)
{
return false;
}
else
{
mParameter = *mCurrentIt;
return true;
}
}
virtual void reset() override
{
mCurrentIt = mVariations.cbegin();
mParameter = *mCurrentIt;
}
private:
typedef typename _ParamVariationContType::const_iterator ConstIteratorType;
// Iterator to the actual values this parameter can yield
ConstIteratorType mCurrentIt;
_ParamVariationContType mVariations;
// Reference to the parameter itself
_DataType& mParameter;
};
class GenericParameterVariator
{
public:
GenericParameterVariator() : mFinished(false)
{
reset();
}
template <typename _ParameterType, typename _ParameterVariationsType>
void registerParameterToVary(
_ParameterType& param,
const _ParameterVariationsType& paramVariations)
{
mParametersToVary.push_back(
std::make_unique<SingleParameterToVary<_ParameterType, _ParameterVariationsType>>(
param, paramVariations));
}
const bool isFinished() const { return mFinished; }
void reset()
{
mFinished = false;
mNumTotalCombinationsVisited = 0;
for (const auto& upParameter : mParametersToVary)
upParameter->reset();
}
// Step into next state if possible
bool createNextParameterPermutation()
{
if (mFinished || mParametersToVary.empty())
return false;
auto itPToVary = mParametersToVary.begin();
while (itPToVary != mParametersToVary.end())
{
const auto& upParameter = *itPToVary;
// If we are the very first configuration at all, do not vary.
const bool variedSomething = mNumTotalCombinationsVisited == 0 ? true : upParameter->varyNext();
++mNumTotalCombinationsVisited;
if (!variedSomething)
{
// If we were not able to vary the last parameter in our list, we are finished.
if (std::next(itPToVary) == mParametersToVary.end())
{
mFinished = true;
return false;
}
++itPToVary;
continue;
}
else
{
if (itPToVary != mParametersToVary.begin())
{
// Reset all parameters before this one
auto itBackwd = itPToVary;
do
{
--itBackwd;
(*itBackwd)->reset();
} while (itBackwd != mParametersToVary.begin());
}
return true;
}
}
return true;
}
private:
// Linearized parameter set
std::vector<std::unique_ptr<SingleParameterToVaryBase>> mParametersToVary;
bool mFinished;
size_t mNumTotalCombinationsVisited;
};
Possible usage:
GenericParameterVariator paramVariator;
size_t param1;
int param2;
char param3;
paramVariator.registerParameterToVary(param1, std::vector<size_t>{ 1, 2 });
paramVariator.registerParameterToVary(param2, std::vector<int>{ -1, -2 });
paramVariator.registerParameterToVary(param3, std::vector<char>{ 'a', 'b' });
std::vector<std::tuple<size_t, int, char>> visitedCombinations;
while (paramVariator.createNextParameterPermutation())
visitedCombinations.push_back(std::make_tuple(param1, param2, param3));
Generates:
(1, -1, 'a')
(2, -1, 'a')
(1, -2, 'a')
(2, -2, 'a')
(1, -1, 'b')
(2, -1, 'b')
(1, -2, 'b')
(2, -2, 'b')
For sure, this can be further optimized/specialized. For instance you can simply add a hashing scheme and/or an avoid functor if you want to avoid effective repetitions. Also, since the parameters are held as references, one might consider to protect the generator from possible error-prone usage via deleting copy/assignement constructors and operators.
Time complexity is within the theoretical permutation complexity range.

Don't know what generates this 'Segmentation Fault' error

I'm currently making a simulation of an autonomous car for my AI class. The car's constructor receives the board as a parameter so it can set the position of the car and add the first node to the search tree, so it can search an optimum path from the Starting Position to the Finishing Position. The thing is, the board generates without any problem, but when I try to pass it to the car's constructor, it results in a Segmentation fault (core dumped) error.
I used a debugger (gdb), ran the code in it and made a back-trace; and the problem came from here:
void node_c::add_child(node_c* chld)
{ int i;
for (i = 0; i < MAX_CHILDREN; i++)
{ if (children_[i] == NULL) //This line's the problem
break;
}
if (children_[i] != NULL)
{ cout << endl << "You can't add any more children." << endl;
return;
}
else children_[i] = chld;
}
Note: 'children_' contains a maximum of 4 children of a search_tree's node, and is a custom vector_c class I had to make.
This is the operator that fails and the function it calls:
template <typename TDato>
TDato& vector_c<TDato>::operator [](int position) { return get_data(position); }
template <typename TDato>
TDato& vector_c<TDato>::get_data(int a) const { return data_[a]; }
I thought that it might be a type error in the comparison if (children_[i] == NULL) so I made a custom operator that returned an object (TDato), not a reference to an object (TDato&), but it didn't work.
I can't imagine what could be causing this and/or how to solve it.
Thanks in advance.
Edit 1: Here's a google drive link to the project as even a minimal reproducible example would be too large to be easy to read in a Stack Overflow question. It's not very big, I promise (less than 1 MB).
Edit 2: Here's the most I could do to make the reproducible example minimal, as the question got closed for not including it.
main.cpp
#include "../include/board_s.hpp"
#include "../include/car_c.hpp"
using namespace std;
int main(void)
{ board_s<int> board(20, 20);
board.file_depiction();
car_c car(board);
board.write(cout);
return 0;
}
Here, the problem comes when the constructor of car_c is called. It should create an car_c object.
board_c.hpp
#ifndef __BOARD_S__
#define __BOARD_S__
#include <cstdio>
#include <iostream>
#include <cstring>
#include <random>
#include <fstream>
#include <utility>
#include "matrix_c.hpp"
#include "tree_c.hpp"
using namespace std;
template <typename TDato = int>
class board_s: public matrix_c<TDato>
{ private:
pair<int, int> starting_pos;
pair<int, int> finishing_pos;
public:
board_s(int, int);
~board_s(void);
pair<int, int> get_start(void);
void file_depiction(void); //Generates obstacles and starting/finishing points as depicted in board_depiction.txt.
virtual ostream& write(ostream&);
int distance(pair<int, int>&) const; //Returns the distance from a given position to the finishing point
private:
bool object_setter(string, int&, int&);
int object_identifier(string&) const; //Given the name of the object ("NEW OBSTACLE" [1], "STARTING POSITION" [2] or "FINISHING POSITION" [3]) returns it's code
};
template class board_s<int>;
#endif
board_c.cpp
#include "../include/board_s.hpp"
#include "matrix_c.cpp"
using namespace std;
//The constructor fills the board with empty boxes.
template <typename TDato>
board_s<TDato>::board_s(int m, int n):
matrix_c<TDato>::matrix_c(m + 2, n + 2)
{ for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
matrix_c<TDato>::at(i, j) = 0;
for(int i = 0; i < n + 2; i++)
{ matrix_c<TDato>::at(0, i) = 1;
matrix_c<TDato>::at(m + 1, i) = 1;
}
for(int i = 0; i < m + 2; i++)
{ matrix_c<TDato>::at(i, 0) = 1;
matrix_c<TDato>::at(i, n + 1) = 1;
}
starting_pos.first = 0;
starting_pos.second = 0;
finishing_pos.first = 0;
finishing_pos.second = 0;
}
template <typename TDato>
board_s<TDato>::~board_s(void){}
template <typename TDato>
pair<int, int> board_s<TDato>::get_start(void) { return starting_pos; }
template <typename TDato>
void board_s<TDato>::file_depiction(void)
{ string line;
int x, y, i;
std::ifstream bd;
bd.open("board_depiction.txt");
if (bd.is_open())
{ getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
matrix_c<TDato>::resize(x + 2, y + 2);
getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("STARTING POSITION", x, y);
getline(bd, line);
getline(bd, line);
i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("FINISHING POSITION", x, y);
while (getline(bd, line))
if (line[0] != 'O')
{ i = line.size() - 1;
y = matrix_c<TDato>::strtoi(line, i);
i--;
x = matrix_c<TDato>::strtoi(line, i);
object_setter("NEW OBSTACLE", x, y);
}
}
else cout << "ERROR";
}
template <typename TDato>
ostream& board_s<TDato>::write(ostream& os)
{ int temp = matrix_c<TDato>::get_n() - 2 + (4 * (matrix_c<TDato>::get_n() - 2));
os << " ";
for (int i = 1; i < temp; i++)
os << "_";
os << " " << endl << "|";
for (int i = 1; i < matrix_c<TDato>::get_m() - 1; i++)
{ for (int j = 0; j < 2; j++)
{ for (int k = 1; k < matrix_c<TDato>::get_n() - 1; k++)
switch (matrix_c<TDato>::at(i, k))
{ case 1:
os << "████|";
break;
case 2:
if (j == 0)
os << " CC |";
else os << "_CC_|";
break;
case 3:
if (j == 0)
os << " FF |";
else os << "_FF_|";
break;
default:
if (j == 0)
os << " |";
else os << "____|";
}
os << endl;
if (j == 0) os << "|";
}
if (i < matrix_c<TDato>::get_m() - 2) os << "|";
}
os << endl;
return os;
}
template <typename TDato>
int board_s<TDato>::distance(pair<int, int>& pos) const
{ int d = (finishing_pos.first - pos.first) + (finishing_pos.second - pos.second);
if (d < 0) return (d * (-1));
else return d;
}
template <typename TDato>
bool board_s<TDato>::object_setter(string name, int &x, int &y)
{ if((x > 0) && (x < matrix_c<TDato>::get_m() - 1) && (y > 0) && (y < matrix_c<TDato>::get_n() - 1) && (matrix_c<TDato>::at(x, y) == 0))
{ matrix_c<TDato>::at(x, y) = object_identifier(name);
cout << endl << endl << "The " << name << " has been set in (" << x << ", " << y << ")" << endl;
if (name == "STARTING POSITION")
{ starting_pos.first = x;
starting_pos.second = y;
}
else if (name == "FINISHING POSITION")
{ finishing_pos.first = x;
finishing_pos.second = y;
}
return true;
}
else
{ cout << endl << "The coordinates that you intriduced were out of reach or the position wasn't free." << endl;
return false;
}
}
template <typename TDato>
int board_s<TDato>::object_identifier(string &name) const
{ if (name == "NEW OBSTACLE")
return 1;
else if (name == "STARTING POSITION")
return 2;
else if (name == "FINISHING POSITION")
return 3;
else return 0;
}
matrix_c.hpp
#ifndef __MATRIX_C__
#define __MATRIX_C__
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <cstring>
#include "vector_c.hpp"
using namespace std;
template <typename TDato>
class matrix_c //Template matrix class implemented with a vector.
{ private:
int m_;
int n_;
vector_c<TDato> v_;
public:
matrix_c(void); //Empty constructor
matrix_c(int, int); //Constructor with dimensions
~matrix_c(void);
void resize(int, int);
TDato& at (int, int); //Redirects to position (x, y)
virtual TDato& operator()(int, int); //Operator for at(int, int)
int get_m(void) const;
int get_n(void) const;
private:
int pos(int, int);
protected:
int ctoi(char&) const;
int strtoi(string&, int&) const;
};
#endif
matrix_c.cpp
#include "../include/matrix_c.hpp"
using namespace std;
template <typename TDato>
matrix_c<TDato>::matrix_c(void):
m_(0),
n_(0),
v_() {}
template <typename TDato>
matrix_c<TDato>::matrix_c(int m, int n):
m_(m),
n_(n),
v_(m * n) {}
template <typename TDato>
matrix_c<TDato>::~matrix_c(void) {}
template <typename TDato>
void matrix_c<TDato>::resize(int m, int n)
{ v_.resize(m * n);
m_ = m;
n_ = n;
}
template <typename TDato>
TDato& matrix_c<TDato>::at(int i, int j) { return v_[(pos(i,j))]; }
template <typename TDato>
TDato& matrix_c<TDato>::operator()(int i, int j) { return at(i,j); }
template <typename TDato>
int matrix_c<TDato>::get_m(void) const { return m_; }
template <typename TDato>
int matrix_c<TDato>::get_n(void) const { return n_; }
template <typename TDato>
int matrix_c<TDato>::pos(int i, int j) { return ((n_ * i) + j); }
template <typename TDato>
int matrix_c<TDato>::ctoi(char &c) const
{ int n = c;
return n - 48;
}
template <typename TDato>
int matrix_c<TDato>::strtoi(string &s, int& i) const
{ int n = 0;
int mult = 1;
while ((s[i] != ' ') && (i >= 0))
{ n += ctoi(s[i]) * mult;
mult *= 10;
i--;
}
return n;
}
template class matrix_c<int>;
vector_c.hpp
#ifndef __VECTOR_C__
#define __VECTOR_C__
#include <iostream>
#include <cstdio>
#include <cassert>
using namespace std;
template <typename TDato>
class vector_c
{ private:
int sz_;
TDato* data_;
public:
vector_c(void); //Empty constructor
vector_c(int); //Constructor with size
~vector_c(void);
TDato& get_data(int) const;
void set_data(TDato&, int);
ostream& write(ostream&) const;
TDato& operator [](int);
void resize(int);
private:
void new_vector(void);
void del_vector(void);
};
#endif
vector_c.cpp
#include "../include/vector_c.hpp"
#include "../include/node_c.hpp"
using namespace std;
template <typename TDato>
vector_c<TDato>::vector_c(void):
sz_(0),
data_(NULL) {}
template <typename TDato>
vector_c<TDato>::vector_c(int size):
sz_(size),
data_(new TDato[sz_]) {}
template <typename TDato>
vector_c<TDato>::~vector_c(void)
{ delete[] data_;
data_ = NULL;
}
template <typename TDato>
TDato& vector_c<TDato>::get_data(int a) const { return data_[a]; }
template <typename TDato>
void vector_c<TDato>::set_data(TDato& dat, int a) { data_[a] = dat;}
template <typename TDato>
TDato& vector_c<TDato>::operator [](int position) { return get_data(position); }
template <typename TDato>
void vector_c<TDato>::resize(int sz)
{ del_vector();
sz_ = sz;
new_vector();
}
template <typename TDato>
void vector_c<TDato>::new_vector(void){
data_ = new TDato[sz_];
}
template <typename TDato>
void vector_c<TDato>::del_vector(void)
{ if (data_ != NULL){
delete [] data_;
data_ = NULL;
}
}
template class vector_c<int>;
template class vector_c<node_c*>;
node_c.hpp
#define MAX_CHILDREN 4
#ifndef __NODE_C__
#define __NODE_C__
#include <iostream>
#include <cstdio>
#include <cassert>
#include "vector_c.hpp"
using namespace std;
class node_c
{ private:
node_c* parent_;
vector_c< node_c* > children_;
pair<pair<int, int>, int> data_;
public:
node_c(void);
node_c(int &x, int &y, int &cost);
node_c(pair<pair<int, int>, int>&);
~node_c(void);
void add_child(node_c*);
};
#endif
node_c.cpp
#include "../include/node_c.hpp"
using namespace std;
node_c::node_c(void):
parent_(NULL)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = 0;
data_.first.second = 0;
data_.second = 0;
}
node_c::node_c(int &x, int &y, int &cost):
parent_(NULL)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = x;
data_.first.second = y;
data_.second = cost;
}
node_c::node_c(pair<pair<int, int>, int> &dat):
parent_(NULL),
data_(dat)
{ for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
}
node_c::~node_c(void)
{ parent_ = NULL;
for (int i = 0; i < MAX_CHILDREN; i++)
children_[i] = NULL;
data_.first.first = 0;
data_.first.second = 0;
data_.second = 0;
}
void node_c::add_child(node_c* chld)
{ int i;
for (i = 0; i < MAX_CHILDREN; i++)
{ if (children_[i] == NULL)
break;
}
if (children_[i] != NULL)
{ cout << endl << "You can't add any more children." << endl;
return;
}
else children_[i] = chld;
}
tree_c.hpp
#ifndef __TREE_C__
#define __TREE_C__
#include "node_c.hpp"
using namespace std;
class tree_c
{ private:
node_c* root_;
int depth_;
public:
tree_c(void);
tree_c(node_c*);
node_c* add_node(node_c*, int&, int&, int);
};
#endif
tree_c.cpp
#include "../include/tree_c.hpp"
using namespace std;
tree_c::tree_c(void):
root_(NULL),
depth_(0) {}
tree_c::tree_c(node_c* root):
root_(root),
depth_(1) {}
node_c* tree_c::add_node(node_c* parent, int& x, int& y, int cost)
{ node_c* node = new node_c(x, y, cost);
parent->add_child(node);
}
car_c.hpp
#ifndef __CAR_C__
#define __CAR_C__
#include <iostream>
#include <cstdio>
#include <cassert>
#include "tree_c.hpp"
#include "board_s.hpp"
using namespace std;
class car_c
{ private:
tree_c tree_;
pair<int, int> pos_;
matrix_c<int> visited_;
public:
car_c(void);
car_c(board_s<int>&);
~car_c(void);
};
#endif
car_c.cpp
#include "../include/car_c.hpp"
using namespace std;
car_c::car_c(void):
tree_(NULL)
{ pos_.first = 0;
pos_.second = 0;
}
car_c::car_c(board_s<int>& board):
pos_(board.get_start()),
tree_(tree_.add_node(NULL, pos_.first, pos_.second, 0))
{ visited_(pos_.first, pos_.second) = 1; }
car_c::~car_c(void) {}
Debugging information:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401cc2 in node_c::node_c (this=0x6187d0, x=#0x7ffffffeddf0: 8, y=#0x7ffffffeddf4: 0,
cost=#0x7ffffffedd2c: 0) at src/node_c.cpp:20
20 children_[i] = NULL;
(gdb) bt
#0 0x0000000000401cc2 in node_c::node_c (this=0x6187d0, x=#0x7ffffffeddf0: 8, y=#0x7ffffffeddf4: 0,
cost=#0x7ffffffedd2c: 0) at src/node_c.cpp:20
#1 0x0000000000402007 in tree_c::add_node (this=0x7ffffffedde0, parent=0x0, x=#0x7ffffffeddf0: 8,
y=#0x7ffffffeddf4: 0, cost=0) at src/tree_c.cpp:16
#2 0x0000000000402df6 in car_c::car_c (this=0x7ffffffedde0, board=...) at src/car_c.cpp:15
#3 0x0000000000401403 in main () at src/main.cpp:11
Sorry for the length of my question, but this is the minimal reproducible example I was able to make. If you know another way to recreate my error, let me know so I can improve this.

error C2678: no operator found which takes a left-hand operand of type 'const_Ty' (or there is no acceptable conversion)

Full error info:
error C2678: no operator found which takes a left-hand operand of type 'const_Ty' (or there is no acceptable conversion)
With the following code:
#include <stdio.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <queue>
using namespace std;
struct num_pair
{
int num1, num2;
};
struct coord {
int y;
int x;
};
struct state_info {
vector<string> lines;
coord o;
bool flag;
};
bool is_solved(state_info m) {
bool check = true;
for (int i = 0; i < m.lines.size(); i++) {
for (int j = 0; j < m.lines[i].size(); j++) {
check *= (m.lines[i][j] != 'x');
}
}
return check;
}
state_info try_move(state_info m, num_pair direction) {
//implementation
}
int main(int argc, char *argv[]) {
string filename = argv[1];
ifstream file;
file.open(filename, ios::in);
vector<string> lines;
int line_num = 0;
coord o;
while (!file.eof()) {
line_num++;
string str;
getline(file, str);
str = str.substr(0, str.length() - 2);
for (int i = 0; i < str.length(); i++) {
if (str[i] == 'o' || 'O') {
o.y = line_num;
o.x = i;
}
}
lines.push_back(str);
}
file.close();
map <char, num_pair> DYDX;
map <state_info, vector<char>> visited;
state_info temp;
temp.lines = lines;
temp.o = o;
temp.flag = true;
vector<char> temp1;
visited[temp] = temp1;
queue <state_info> state;//todo
state.push(temp);
while (state.size() != 0) {
state_info currstate = state.front();
if (is_solved(currstate)) {
vector<char> output = visited[currstate];
for (int i = 0; i < output.size(); i++) cout << output[i];
}
map<char, num_pair>::iterator iter;
map<state_info, vector<char>>::iterator it;
for (iter = DYDX.begin(); iter != DYDX.end(); iter++) {
num_pair move = (*iter).second;
state_info newstate = try_move(currstate, move);
if (newstate.flag) {
it = visited.find(newstate);
if (it == visited.end()) {
temp1 = visited[currstate];
temp1.push_back((*iter).first);
visited[newstate] = temp1;
state.push(newstate);
}
}
}
}
return 0;
}
It comes out with a compilation error C2678 which seems to be that somewhere in the code exists a operation that assign a non-const variable to a const. I have no idea where to begin with the debugging.
I checked where this error comes from and it lead me to this section of code.
template<class _Ty = void>
struct less
{ // functor for operator<
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef bool result_type;
constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
Why does this error happen? Is it because of the STL that I use? And any suggestions how to find out where the problem is with the output council?
Maps are sorted data structures and so need an operator< defined on their key type.
map <state_info, vector<char>> visited;
There is no operator< defined for state_info. That is what the error message is telling you.
There are other ways to solve this problem. If defining operator< for state_info seems unnatural to you, then you could pass a comparator type to your map declaration.
map <state_info, vector<char>, state_info_cmp> visited;
with
struct state_info_cmp
{
bool operator()(const state_info& x, const state_info& y) const
{
// true if x is 'less than' y, false otherwise
...
}
};

Postfix calculation with stack class, C++

I am trying to use a custom stack class to calculate an equation in postfix form. For some reason, the program keeps crashing.
Here is the stack header file
#ifndef aStack_h
#define aStack_h
#include <string>
#include <iostream>
using std::string; using std::cout;
class aStack
{
private:
int top, size;
int *stack;
public:
aStack(int s)
{
size = s;
top = -1;
stack = new int [s];
}
~aStack()
{
delete [] stack;
}
void reset();
void push(int);
void pop();
int getTop();
void getSize()
{
std::cout << size;
}
};
#endif
The class implementation file:
#include "aStack.h"
#include <iostream>
using namespace std;
void aStack::pop()
{
if (top == -1)
{ cout << "Stack is already empty.\n";}
stack[--top];
}
void aStack::push(int v)
{
if (top == size)
{ cout << "Stack is full.\n";}
stack[top++] = v;
}
void aStack::reset()
{
top = -1;
}
int aStack::getTop()
{
return top;
}
Here is the main program
#include <iostream>
#include "aStack.h"
#include <string>
using namespace std;
int main()
{
string equation {"35+1*"};
int op, count = 0, *oparray, result;
aStack stack(equation.length());
for (int i = 0; i < equation.length(); i++)
{
if (isdigit(equation[i]))
{
stack.push(equation[i]);
count++;
}
else
{
oparray = new int [count];
for (int o = 0; o < count; o++)
{
oparray[o] = stack.getTop();
stack.pop();
}
switch(equation[i])
{
case '+':
for (int i =0; i < count; i++)
{
op += oparray[i];
count--;
}
stack.push(op);
break;
case '-':
for (int i =0; i < count; i++)
{
op-=oparray[i];
count--;
}
stack.push(op);
break;
case '*':
for (int i =0; i < count; i++)
{
op*=oparray[i];
count--;
}
stack.push(op);
break;
case '/':
for (int i =0; i < count; i++)
{
op/=oparray[i];
count--;
}
stack.push(op);
break;
}
delete [] oparray;
}
}
result = stack.getTop();
cout << result;
}
I know I should not use the "using namespace std;", I was in a hurry. I doubt that would be the cause of my problems. Any help is greatly appreciated.
Your stack class has miscellaneous problems already pointed out in the comments. With those fixed, only a few bugs in the main program remained.
I've used a std::unique_ptr<> in your array instead of a raw pointer and disabled move semantics so it's neither copyable (because of the unique_ptr) nor moveable.
I also added throwing exceptions if you try to access the stack out of bounds.
#include <cctype>
#include <cstddef>
#include <exception>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
template<typename T>
class aStack {
public:
using value_type = T;
explicit aStack(size_t c) :
cap(c), stored(0), stack(std::make_unique<value_type[]>(cap)) {}
aStack(aStack&&) = delete; // moving disabled
void reset() noexcept { stored = 0; }
void push(const value_type& v) {
if(stored == cap) throw std::runtime_error("stack is full");
stack[stored++] = v;
}
void push(value_type&& v) {
if(stored == cap) throw std::runtime_error("stack is full");
stack[stored++] = std::move(v);
}
value_type& pop() {
if(stored == 0) throw std::runtime_error("stack is empty");
return stack[--stored];
}
[[nodiscard]] const value_type& top() const {
if(stored == 0) throw std::runtime_error("stack is empty");
return stack[stored - 1];
}
[[nodiscard]] value_type& top() {
if(stored == 0) throw std::runtime_error("stack is empty");
return stack[stored - 1];
}
[[nodiscard]] size_t capability() const noexcept { return cap; }
[[nodiscard]] size_t size() const noexcept { return stored; }
private:
size_t cap, stored;
std::unique_ptr<value_type[]> stack;
};
When it comes to the main program, the major problem was that you forgot to convert the ASCII value of each digit into an integer.
Another problem was the op calculation. You kept the value from the last iteration instead of grabbing a new value from the stack. There was also an extra allocation of memory that was unnecessary so I removed that. You also had shadowing variables, which didn't cause any error, but makes it really hard to read the code.
int main(int argc, char* argv[]) {
if(argc < 2) {
std::cout << "USAGE: " << argv[0] << " <equation>\n";
return 1;
}
std::string equation(argv[1]);
try {
int op, result;
aStack<int> stack(equation.length());
for(size_t ei = 0; ei < equation.length(); ++ei) {
if(std::isdigit(equation[ei])) {
stack.push(equation[ei] - '0'); // from ASCII to digit
} else {
op = stack.pop(); // start with what's on the stack
switch(equation[ei]) {
case '+':
while(stack.size()) {
op += stack.pop();
}
stack.push(op);
break;
case '-':
while(stack.size()) {
op -= stack.pop();
}
stack.push(op);
break;
case '*':
while(stack.size()) {
op *= stack.pop();
}
stack.push(op);
break;
case '/':
while(stack.size()) {
op /= stack.pop();
}
stack.push(op);
break;
default:
throw std::runtime_error("invalid operation");
}
}
}
result = stack.pop();
if(stack.size() != 0)
throw std::runtime_error("stack not empty when calculation ended");
std::cout << result << '\n';
} catch(const std::exception& ex) {
std::cerr << "Exception: " << ex.what() << '\n';
}
}