I want to pass class name oltosmol as an argument so it will create an object with default constructor. It would normally work but not here. And the problem is only with oltosmol.
error: request for member 'creator' in 'smolifier', which is of non-class type 'StatP::CharProcessor\<StatP::oltosmol\>(StatP::oltosmol)'
namespace StatP
{
class oltosmol
{
public:
oltosmol() {}
char transform(char c)
{
if (c >= 'A' && c <= 'Z')
return c + 'a' - 'A';
return c;
}
};
class Cutifier
{
unsigned period;
unsigned counter;
public:
Cutifier(unsigned p): period(p), counter(0) {}
char transform(char c)
{
if (counter == period)
{
counter = 0;
if (c == ' ')
return '\3';
else if (c >= 'a' && c <= 'z')
return c - 'a' + 'A';
else if (c >= 'A' && c <= 'Z')
return c - 'A' + 'a';
return c;
}
else
{
counter++;
return c;
}
}
};
template<class Transformer>
class CharProcessor
{
Transformer transformer;
public:
CharProcessor(const Transformer &t): transformer(t) {}
String<char> creator(String<char> &s)
{
char *n_data = new char[s.get_length() + 1];
for (unsigned i = 0; i < s.get_length(); i++)
n_data[i] = transformer.transform(s[i]);
n_data[s.get_length()] = '\0';
return String<char>(n_data);
}
void changer(String<char> &s)
{
for (unsigned i = 0; i < s.get_length(); i++)
s[i] = transformer.transform(s[i]);
}
};
}
int main()
{
const char coca_cola[] = "Coca-cola";
String<char> water_name = coca_cola;
copy = water_name;
// ...
StatP::CharProcessor<StatP::oltosmol> smolifier(StatP::oltosmol);
std::cout << smolifier.creator(water_name) << "\n\n";
return 0;
}
I've tried to add () and remove namespace, but it's still doesn't work. The program would run, if I firstly assign object to a variable, but I don't want and shouldn't do that.
This constructor passes pointer to a function which is not a thing you intend to pass:
... smolifier(StatP::oltosmol)
To do the thing you intended you require instantiate your class and than pass it to the CharProcessor:
StatP::oltosmol smol{};
... smolifier(smol);
But in your case better solution to remove reference from constructor and pass it by value and move it inside CharProcessor completely;
CharProcessor(Transformer t): transformer(std::move(t)) {}
...
// And now you can just put braces
CharProcessor<oltsmol> smolifer({});
In your instantiation of smolifier you have to pass an instantiated object. Writing a type in the argument list is invalid syntax.
This is what you need there:
StatP::CharProcessor smolifier(StatP::oltosmol{});
Observe that due to CTAD, you don't actually have to spell out the type argument to the class template because it can be inferred from the constructor argument.
(live demo, with some types replaced because you didn't provide them)
Related
I have a code that uses a while statement. Inside
the conditional expression I do a lookup. At the same time the conditional expression checks the return value:
#include <map>
struct a {
a *up;
std::map<int,int> tbl;
};
void p(a *_a, int id) {
decltype(_a->tbl)::iterator i;
while (_a && (i = _a->tbl.find(id)) != _a->tbl.end()) {
i->second += 1;
_a = _a->up;
}
}
int main(int arc, char **argv) {
a _a1{0,{{0,10},{1,10}}};
a _a0{&_a1,{{2,11},{3,11}}};
p(&_a0, 0);
return 0;
}
However I would like to get rid of the explicit declaration of i. I would like to use auto. In pseudocode:
...
void p(a *_a, int id) {
while (_a && ((auto i = _a->tbl.find(id))) != _a->tbl.end()) {
i->second += 1;
_a = _a->up;
}
}
...
Is there a construct in c++11/14/17 that supports this kind of declarations inside an expression? Not only while(auto i = 1) {...} style declarations? Maybe there are some new features that allow this?
How about separating the two conditions? The main one for the loop to continue is _a, and the secondary one (which may always be true) is _a->tbl.find(id) != _a->tbl.end(). Return on its negation:
void p(a *_a, int id) {
while (_a) {
auto i = _a->tbl.find(id);
if (i == _a->tbl.end()) {
return;
}
i->second += 1;
_a = _a->up;
}
}
I have a template class that I am testing:
class SparseMat {
private:
FHvector<FHlist<MatNode<Object>>> matrix;
int numOfRows, numOfCols;
const Object defaultValue;
public:
SparseMat(int r, int c, const Object& defaultVal);
const Object & get(int r, int c) const;
bool set(int r, int c, const Object& x);
};
template <class Object>
SparseMat<Object>::SparseMat(int r, int c, const Object& defaultVal) : defaultValue(defaultVal) {
numOfRows = r;
numOfCols = c;
matrix.resize(numOfRows);
for (int counter = 0; counter < numOfRows; counter++) {
FHlist<MatNode<Object>> currentRow;
matrix.push_back(currentRow);
}
}
template <class Object>
bool SparseMat<Object>::set(int r, int c, const Object& x) {
if (r >= numOfRows || r < 0 || c < 0 || c >= numOfCols) {
return false;
}
if (r == 9 && c == 9) {
cout << x << endl;
}
if (r == 9 && c == 9) {
cout << x << endl;
}
for (FHlist<MatNode<Object>>::iterator iter = matrix[r].begin(); iter != matrix[r].end(); ++iter) {
if ((*iter).getCol() == c) {
if (x == defaultValue) {
matrix[r].erase(iter);
return true;
}
else {
(*iter).data = x;
return true;
}
}
}
matrix[r].push_back(MatNode<Object>(c, x));
return true;
}
template <class Object>
const Object & SparseMat<Object>::get(int r, int c) const {
if (r >= numOfRows || r < 0 || c < 0 || c >= numOfCols) {
throw OutOfBoundsException();
}
FHlist<MatNode<Object>> wantedRow = matrix[r];
for (FHlist<MatNode<Object>>::iterator iter = wantedRow.begin(); iter != wantedRow.end(); ++iter) {
if ((*iter).getCol() == c) {
return (*iter).getData();
}
}
return NULL;
}
MatNode is as follows:
template <class Object>
class MatNode
{
protected:
int col;
public:
Object data;
MatNode(int cl = 0, Object dt = Object()) : col(cl), data(dt) { }
int getCol() const { return col; }
const Object & getData() const {return data; }
};
The immensely strange thing is my two outputs print two different things. The first prints 21, as expected. The second prints out some random float, which is definitely not expected as I have changed nothing with x between the two outputs.
#include <iostream>
using namespace std;
#include "FHsparseMat.h"
#define MAT_SIZE 100000
typedef SparseMat<float> SpMat;
int main()
{
SpMat mat(MAT_SIZE, MAT_SIZE, 0);
mat.set(3, 9, 21);
cout << mat.get(3, 9) << endl;
mat.set(9, 9, 21);
cout << mat.get(9, 9) << endl;
mat.set(9, 9, mat.get(3,9));
cout << mat.get(9, 9) << endl;
}
Here is my tester. If I replace mat.get(3,9) with the hard coded value of 21, the issue disappears, if that helps.
get() has a return type of const Object &.
As a result, the final line of the function
return 0; // source code says NULL but preprocessor replaces that with 0
is returning a dangling reference to a temporary Object implicitly constructed with the value 0.
Using that dangling reference will, of course, cause undefined behavior.
It's not completely clear why that line is reached, but the logic that erases an item if you write the same value to the same location certainly seems suspicious. IMO you should only remove an item when the value written is zero.
The issue is that Object MatNode::getData() const is not returning a reference, and you are returning a reference in const Object & SparseMat<Object>::get(int r, int c) const. Change it to:
Object SparseMat<Object>::get(int r, int c) const.
so I'm making a C++ Checkers like game for my AI class. I've run into a bit of a hiccup that's driving me insane, each opponent piece is a struct that contains a direction: bool left; bool right; When I try and change one of the values to be true, it doesn't seem to change. It seems to be a scope issue but i don't know why, I've followed it through using vs debug tool. Here's some of the code:
typedef struct {
int pos;
int num;
bool left;
bool right;
}opp;
int scoreOp(opp o){
if (scoreMoveOp(o.pos + 7) == 10){
o.left = true;
return 10;
}
else if (scoreMoveOp(o.pos + 9) == 10){
o.right = true;
return 10;
}
int scoreOp(opp o){
if (scoreMoveOp(o.pos + 7) == 10){ //scoreMoveOp essentially returns ten.
o.left = true;
return 10;
}
else if (scoreMoveOp(o.pos + 9) == 10){
o.right = true;
return 10;
}
and is all is called:
void checkOPPListForX(){
for (int i = 0; i < O1Moves.size(); i++){
if (X == O1Moves[i].second){
//cout << "O1 has it, and its score is: " << scoreOp(O1) << endl;
O1Score = scoreOp(O1);
O1Check = true;
}
else O1Check = false;
}
checkOPPListForX();
if (O1Score > O2Score && O1Score > O3Score && O1Score > O4Score){
//move O1;
//O1.pos
if (O1.left)
O1.pos = O1.pos + 7;
else if (O1.right)
O1.pos = O1.pos + 9;
}
You're passing the variable to the scoreOp function by value, which means that the function gets a copy. And modifying a copy will of course not modify the original.
You need to pass the argument by reference instead:
int scoreOp(opp& o){ ... }
// ^
// |
// Note ampersand here, which means that the argument is passed by reference
The easiest way is to put your function inside the struct :
typedef struct {
int pos;
int num;
bool left;
bool right;
int scoreOp() {.....}
}opp;
and then you can call it with opp.ScoreOp()
This solution is if you're not too comfortable passing by reference
I'm trying to create a program that takes a polynomial function from the user, counts the number of terms it has, creates an array large enough to store all of the terms, and then stores the terms there. The problem is that I'm not quite sure how to add a private class variable (or more specifically, a string array) AFTER the program determines how the large the function is. I need this string array to be a private class variable because I want to be able to access its contents through other class methods to do things like, for example, cout each of the function terms.
main.cpp:
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
int main()
{
Function func1;
func1.coutFuncTerms();
func1.coutFunc();
return 0;
}
Function.h:
#ifndef FUNCTION_H
#define FUNCTION_H
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
class Function
{
public:
Function();
~Function();
void removePlus(string*);
void removeWhitespace(string*);
void setFuncTerms();
void splitTerms();
void coutFuncTerms();
void coutFunc();
void coutTerms(string);
protected:
private:
string func;
int funcTerms;
};
#endif
Function.cpp:
#include <iostream>
#include <string>
#include "Function.h"
using namespace std;
// Function Constructor
//
// Stores a function inputted by the user
// Adds a null character ('\0') to the end of a string
// Erases a redundant '+' sign at the beginning of a string if there's one there
// Erases any whitespace characters in a string
// Stores the number of terms in the function
Function::Function()
{
getline(cin, func);
setFuncTerms();
//splitTerms();
}
Function::~Function()
{
}
// removePlus Function
//
// Erases a redundant '+' sign at the beginning of a string if there's one there
void Function::removePlus(string* func)
{
if(func->at(0) == '+')
{
func->erase(0, 1);
}
}
// removeWhitespace Function
//
// Erases any whitespace characters in a string
void Function::removeWhitespace(string* func)
{
for(int x = 0; unsigned(x) < func->length() - 1; x++)
{
while(func->at(x) == ' ' || func->at(x) == '\t')
{
func->erase(x, 1);
}
}
}
// setFuncLength Function
//
// Finds the number of terms in a Function object's 'func' variable
// Assigns this number to the object's 'funcLength' variable
void Function::setFuncTerms()
{
funcTerms = 0;
for(int funcTerm = 0; unsigned(funcTerm) < func.length(); funcTerm += 1)
{
bool isAPotentialTerm = false;
bool isATrueTerm = false;
if(func.at(funcTerm) == '+' || func.at(funcTerm) == '-')
{
isAPotentialTerm = true;
}
if(isAPotentialTerm == true)
{
for(int newFuncTerm = funcTerm + 1; unsigned(newFuncTerm) < func.length(); newFuncTerm += 1)
{
if(func.at(newFuncTerm) == '+' || func.at(newFuncTerm) == '-')
{
break;
}
if(func.at(newFuncTerm) != ' ' && func.at(newFuncTerm) != '\t')
{
isATrueTerm = true;
break;
}
}
}
if(isATrueTerm)
{
funcTerms++;
}
}
}
// splitTerms Function
//
// Calls the splitTerm function for each term in 'func' according to the function array 'funcArray'
void Function::splitTerms()
{
string funcArray[funcTerms];
int tempFuncLength = 0;
for(int funcTerm = 0; unsigned(funcTerm) < func.length(); funcTerm += 1)
{
bool isAPotentialTerm = false;
bool isATrueTerm = false;
if(func.at(funcTerm) == '+' || func.at(funcTerm) == '-')
{
isAPotentialTerm = true;
}
if(isAPotentialTerm == true)
{
for(int newFuncTerm = funcTerm + 1; unsigned(newFuncTerm) < func.length(); newFuncTerm += 1)
{
if(func.at(newFuncTerm) == '+' || func.at(newFuncTerm) == '-')
{
break;
}
if(func.at(newFuncTerm) != ' ' && func.at(newFuncTerm) != '\t')
{
isATrueTerm = true;
break;
}
}
}
if(isATrueTerm)
{
string temp;
for(; unsigned(funcTerm) < func.length() && func.at(funcTerm) != '+' && func.at(funcTerm) != '-'; funcTerm += 1)
{
funcArray[tempFuncLength].append(1, func.at(funcTerm));
}
tempFuncLength++;
}
}
for(int x = 0; x < funcTerms; x++)
{
cout << "Term " << x + 1 << " is: " << funcArray[x] << endl;
}
}
void Function::coutFuncTerms()
{
cout << "Terms: " << funcTerms << endl;
}
void Function::coutFunc()
{
cout << "Function: " << func << endl;
}
void Function::coutTerms(string funcArrayTerm)
{
/*for(int x = 0; x < funcLength; x++)
{
cout << "Term " << x << " is: " << funcArray[x] << endl;
}*/
//cout << funcArray[0] << endl;
}
I highly recommend you change your design.
A function is a container of terms. So let's define a term:
A term minimally has a coefficient and an exponent:
struct Fundamental_Term
{
double coefficient;
int exponent;
};
If your function is only in terms of one variable, all you need is the Fundamental_Term. Otherwise, you need to have the base variable name:
struct Term_With_Base
: public Fundamental_Term
{
std::string variable_name;
};
Note: if you can't use inheritance, copy the member variables of Fundamental_Term into Term_With_Base.
Remember a function is a collection or container of terms. Assuming a function with multiple bases, we can declare:
struct Function
{
std::vector<Term_With_Base> terms;
};
Evaluation of Terms
To evaluate a function, f(x), all terms must be evaluated and their results summed.
This decomposes into two requirements: 1) Terms must have an evaluation method; 2) The function class must have an evaluation method that sums the terms.
So, we add an evaluation function to the base class:
struct Fundamental_Term
{
double coefficient;
int exponent;
double evaluate(double value)
{
return coefficient * pow(value, exponent);
}
};
struct Function
{
std::vector<Term_With_Base> terms;
double evauate(double value)
{
const unsigned int quantity = terms.size();
double result = 0.0;
for (unsigned int i = 0; i < quantity; ++i)
{
result = result + terms[i].evaluate(value);
}
return result;
}
};
When creating a function from a string, a preference is to create a constructor of Fundamental_Term that takes a string parameter. The term object should read its coefficient, variable name and exponent, not the Function container.
For more examples, search StackOverflow for "c++ parse term evaluation".
Edit 1: Inserting terms
One method to insert terms, is to have a method in the term data structure that loads a term from a string:
bool
Fundamental_Term ::
load_from string(const std::string& input,
unsigned int & start_position)
{
bool term_is_valid = false;
// Parse the string and load appropriate fields.
// Set the start position to the first position after the valid term.
// Set term_is_valid to true if the term has valid syntax.
return term_is_valid;
}
The Function object would have a member to load terms from a string.
bool
Function ::
load_terms_from_string(const std::string& input)
{
Term_With_Base term;
unsigned int position_in_string = 0;
bool term_is_valid = true;
while (term_is_valid && (position_in_string < input.size()))
{
term_is_valid = term.load_from_string(input, position_in_string);
if (term_is_valid)
{
terms.push_back(term);
}
}
}
The std::vector used to contain the terms will expand as necessary with each additional term that is parsed. The loop will terminate when the string is parsed or there is an invalid term.
For my c++ class we were given the task of writing a template class who's class object's type is defined by the user using templates.
Code snipit from main:
if (dataType == "1" || dataType == "int") {
simpleVector<int> userArray;
} else if (dataType == "2" || dataType == "double") {
simpleVector<double> userArray;
} else if (dataType == "3" || dataType == "char") {
simpleVector<char> userArray;
} else if {
simpleVector<string> userArray;
}
userArray.setDefaultArray();
From this I get error code C2065 - undeclared identifier error. I see why I am getting the error but i do not know how I can declare userArray before I know the data type.
Source Code:
#include <stdio.h>
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
template<class T>
class simpleVector {
public:
void setDefaultArray ();
void setArraySize (int size);
void copy (T *arr);
void desctruct ();
int getArraySize ();
T getElementAt (int index);
void fillArray();
private:
int arraySize;
T *myArray;
};
int main () {
string dataType;
int arraySize;
bool loopCondition = false;
do {
cout << "Data Type:";
cin >> dataType;
if (dataType == "1" || dataType == "2" || dataType == "3" || dataType == "4"
|| dataType == "int" || dataType == "double" || dataType == "char" || dataType == "string") {
loopCondition = false;
} else {
cout << "WARNING: invalid data type entered." << endl;
cout << "Valid entries are (1.int, 2.double, 3.char, 4.string)" << endl;
loopCondition = true;
}
} while (loopCondition);
if (true)
int num = 9;
else
int num = 7;
int num2 = num;
//simpleVector userArray; //?? Review
if (dataType == "1" || dataType == "int") {
simpleVector<int> userArray;
} else if (dataType == "2" || dataType == "double") {
simpleVector<double> userArray;
} else if (dataType == "3" || dataType == "char") {
simpleVector<char> userArray;
} else if (dataType == "4" || dataType == "char") {
simpleVector<string> userArray;
}
userArray.setDefaultArray();
cout << "Number of Inputs:";
cin >> arraySize;
userArray.setArraySize(arraySize);
userArray.fillArray();
return 0;
}
//Should call desctruct before this if reusing.
template<class T>
void simpleVector<T>::setDefaultArray() {
arraySize = 0;
myArray = NULL; //note: NULL is case sensitive (#include <stdio.h>)
}
template<class T>
void simpleVector<T>::setArraySize (int size) {
myArray = new T[size];
}
template<class T>
void simpleVector<T>::copy (T *arr) {
//ToDo
}
template<class T>
void simpleVector<T>::desctruct () {
//ToDo
}
template<class T>
int simpleVector<T>::getArraySize () {
//ToDo
}
template<class T>
T simpleVector<T>::getElementAt (int index) {
//ToDo
}
template<class T>
void simpleVector<T>::fillArray() {
cout << "Enter Array Values" << endl;
for (int i; i < arraySize; i++) {
cout << "Element " + i + ":";
cin >> myArray[i];
}
}
Thanks,
Mike
The code in Eugene's answer looks great, but is maybe too complicated for learning C++?
A very simple solution could look like this
declare a class vectorBase, which declares all the methods you need in all your vectors
let the templated class inherit from vectorBase
template
class simpleVector : public vectorBase { ...
then declare a pointer of type vectorBase before your
if (dataType == "1" || dataType == "int") ...
in the if-block assign the newly created userArrays to the base class pointer
later, access the methods through the baseClass pointer, which is identical for all specific template classes
You can't do this, because types determination are a compile-time process. Use inheritance instead templates, if you want to determine types at runtime.
Also I can suggest you the "variant" pattern. For example:
#include <memory>
#include <string>
class variant
{
public:
template <class T>
variant& operator = (T const& t)
{
typedef type<T> assign_type;
object = std::auto_ptr<assign_type>(new assign_type(t));
return *this;
}
template <class T>
operator T ()
{
typedef type<T> assign_type;
assign_type& type = dynamic_cast<assign_type&>(*object);
return type.get();
}
private:
class base
{
public:
virtual ~base() {}
};
typedef std::auto_ptr<base> base_ptr;
template <class T>
class type : public base
{
public:
type(T const& t)
: object(t)
{
}
T get() const
{
return object;
}
private:
T object;
};
base_ptr object;
};
struct dummy
{
int a;
int b;
int c;
};
int main()
{
variant v1, v2, v3, v4;
v1 = 2;
v2 = 5.0f;
v3 = std::string("Pot of gold");
v4 = dummy();
int i = v1;
float f = v2;
std::string s = v3;
dummy d = v4;
return 0;
}
As I understand, the intention of this problem is to teach how template usage is limited by type definition on compile time. It's pretty straightforward that user's choice will be limited by some list of types which developer cared to explicitly specify. Now the question is - how it affects the resulting program?
First, you should realize that code-paths for all possible values of your template argument will be instantiated on compile time. In other words, binary code for setDefaultArray, setArraySize, fillArray and other member functions which you explicitly or implicitly call in your generic algorithm will be generated for int, double, char and std::string template arguments. There's not much you can do to optimize it out of the executable.
However, what you can do is to decide how to store your object(s) in memory in most efficient way. And obviously for your task you need only a single instance of some simpleVector at a time. So you may think of a memory block big enough to keep any simpleVector instantiation and also designating which of them it currently contains. In C++ it will sound like this:
struct SimpleVectors {
VectorTypeEnum vte;
union {
simpleVector<int> v_int;
simpleVector<double> v_double;
simpleVector<char> v_char;
simpleVector<string> v_string;
};
};
Please note that you can do it only with POD-structures (google for the definition).
Inheritance-based approaches eventually boil-down to this kind of layout.
To complete the picture, we just need to connect a processing logic to this data structure:
template <
typename T
>
inline void handleTask (
simpleVector <
T
>
& v
)
{
int arraySize;
v.setDefaultArray();
cout << "Number of Inputs:";
cin >> arraySize;
v.setArraySize(arraySize);
v.fillArray();
}
The benefit of this approach over the inheritance-based is that you can make your class member functions inline, and the compiler will take care that their calls will be an order of magnitude faster than the virtual member functions.
And finally, the key piece of your main function will look as:
SimpleVectors userArray;
// we don't really need to initialize userArray.vte in this sample
if (dataType == "1" || dataType == "int") {
handleTask(userArray.v_int);
} else if (dataType == "2" || dataType == "double") {
handleTask(userArray.v_double);
} else if (dataType == "3" || dataType == "char") {
handleTask(userArray.v_char);
} else if (dataType == "4" || dataType == "string") {
handleTask(userArray.v_string);
}