Compiling error | cannot compile cpp program due to compiler parser - c++

Short Description
I am trying to compile a short lambda to convert a giving input to string format. My overall class uses a template, i.e template <typename T>. I want to overload << to print-out an object which can be of any type; i.e, int, string, etc. For example, let's say that my object is {int age: 12, int* left: null, int* right: null}, I should be able to print something like "{value: "12", left: undefined, right: undefined}". In addition, if object = {string comment: "Distance learning....", int* left: undefined, int* right: undefined}, I should print out, "{value: "Distance learning....", left: undefined, right: undefined}". Below is a copy of the lambda function mark-up to convert from any data-type to a string.
std::function<std::string(T)> toString; //declares the blueprint for the lambda function, notice that I am returning a string, and expecting an object of type T, which can be of any type since i'm using a template.
toString = [](T value) -> std::string { //Begins the the body of the function
if (typeid(std::string).name() == typeid(T).name())
{ // not the best way to do this, but here I am checking that the input is already a string, in which case I do not need to convert or anything.
return value; //if the input 'value' is already a string, simply return it.
}
//do some stuff to convert the date into a string
return; // return the final 'value' in string format.
};
~Sorry in advance if my comments were confusing.
Problem
The idea works on paper, however, the problem happens when I have a data-type that is not of type string. Let's say that T == int, walking through the code, the if statement will be skipped, assuming that my condition is set-up correctly, and I should move down. This means that I will not return an int when the function blueprint says that I will return a string.
However, when the compiler goes through my code, it reads it and thinks that I am trying to send-back an int when the function is supposed to send back a string and it throws an error. "no viable conversion from returned value of type 'int' to function return type 'std::string'"
for example,
//Let T = int, value = 12, so the below parameter equals, int value, which holds the value of 12.
toString = [](T value) -> std::string {
if (typeid(std::string).name() == typeid(T).name())
{ //should failed since typeid(int).name != typeid(std::string).name
return value;
}
//do some stuff to convert the date into a string
return; // return the final 'value' in string format.
};
//However, when the compiler parses the code, it thinks that I am trying to return value, which is of type int. But the function is supposed to return a string.
//In reality, this should not happen since my if statement will take care of it.
Does anyone know a work around for this or any idea on how to fix my logic?

You need at least C++17 to use if constexpr.
With if constexpr you can write something as
if constexpr ( std::is_same_v<T, std::string> )
return value
else
{
// something else that return a std::string
}
Only this way you can exclude from the compilation return value, when T isn't std::string, and the body for the else case, otherwise.
Observe that I've used the std::is_same type-trait to check if T and std::string are the same type. std::is_same is something that the compiler decide compile time. Your typeid(...).value() is a run-time value. Suggestion: prefer compile-time type-traits, when possible.
But I need to see a more complete example to show how to use if constexpr in your class/struct.
Before C++17, you need two different functions to initialize tostring.

Related

I need help writing a function that checks the data type of another variable

Hi i'm having trouble making a function that checks the data type of a variable and checks it to make sure if a data type is similar to it in C++. Here's my code so far:
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
int typeCheck(string words, string typeWanted);
//make number assurance function .
string word;
cin >> word;
typeCheck(word, "string");
}
int typeCheck(string words, string typeWanted) {
if (typeid(words).name() != typeid(typeWanted).name()) {
cin.clear();
cin.ignore();
return 0;
}
else if (typeid(words).name()== typeid(typeWanted).name())
cout << "All good";
}
When I run the code it keeps saying the same output which is: All good even if I put a string or an int when its not the correct one. Instead of saying this I want it to clear the buffer and ignore it. Can anyone help me with this problem? Thanks in advance!
C++ is a statically typed language, meaning that the type is known at compile time. It will never be known only at run time.
What that means is that in your example:
int typeCheck(string words, string typeWanted);
both words and typeWanted will always be strings. If it is ever not a string, it will fail to compile. Thus, using typeid() in this situation is somewhat pointless. Your if statement will always be false, and your else-if statement will always be true.
Instead, you would want to use typeid() when you don't know they will be the same type, like in some sort of template situation:
template <class WordsType, class TypeWantedType>
int typeCheck(WordsType words, TypeWantedType typeWanted);
Here, a typeid() comparison makes more sense, because you don't really know if words and typeWanted are both strings.
You could do something like this instead:
template <class WordsType>
int typeCheck(WordsType words, string typeWanted) {
if (typeid(words).name() != typeWanted) {
//...
}
// ...
}
This would compare an unknown type to a wanted type.
Finally, there is another option, #RSahu's option from the comments:
if(words == typeWanted) {
//...
}
This will compare the input the user gave to the string "string".
It's unclear to me what you want to do exactly, so I can't recommend which one you should use, but at least now you have a couple of options.
It is because you are converting the type to string eaither way so it will allways trigger as correct as long as it is a string in the function input.
I would recommend that you use a template type so that whatever you enter into the TypeCheck() function will retain its type.

C++ int function. How do I detect false when zero is a valid return value?

I have a function that parses some input from std::cin and returns an integer value on success. I need to detect, based on the return value, if something went wrong when parsing input. Zero is a valid return. What can I use to differentiate between valid zero and "bad input"?
If I need to post code as an example, just let me know. Thanks!
[EDIT]
int parseInput(){
int calculatedValue = 0;
bool parseOk = true;
/* Parse cin for valid input.*/
if (parseOk) {
/* Perform calculation. Can be zero */
}
return calculatedValue; // Any integer is valid
}
This would be the perfect job for std::optional. Your best alternative, with regards to notify at return value, is to implement a similar class.
Alternatively, you should really use an exception. Exceptions are made exactly to notify the user of your function that something went wrong.
You can use an boolean flag for checking if something went wrong, it is common practice (for instance, Qt library uses it) to do something like:
int getIntegerStuffFromInput(bool & ok);
or
bool getIntegerStuffFromInput(int & value);
When you read numbers from std::cin, the most important thing is not to read directly into an int. Instead, you use std::getline to read a whole line of input into an std::string. This way you can detect wrong input much more easily.
Once the line has been entered, you convert the resulting std::string to an int.
std::string input_line;
std::getline(std::cin, input_line);
// input_line now contains a whole line of input
In C++11, you just use std::stoi for the conversion:
int const input = std::stoi(input_line);
This function will throw an exception if the string cannot be converted to an integer number.
In pre-C++11, you use std::istringstream:
std::istringstream is(input_line);
int input = 0;
is >> input;
The following code then checks if the line could be correctly converted to an integer number or not:
if (!is)
{
// error
}
"What can I use to differentiate between valid zero and "bad input"?"
You have basically three choices
If you need to handle all integers as a valid return value:
Throw an exception, that can be handled outside from your function call
Have a dedicated output parameter passed by reference, and return bool from your function, false indicates bad input.
If negative integers aren't a valid return value:
Just return a negative value and test for result < 0.

How can I return a string value from a function in C++

#include <iostream>
#include <string>
using namespace std;
std::string dispCard(int card)
{
string textCard = "help";
//cout << textCard;
system("pause");
return textCard;
}
int main()
{
// Using this area to test functions for now
cout << dispCard(14);
return 0;
}
Uncommenting the cout line actually does display the value. But I cannot return the value in the string.
Honestly, I have no idea why this isn't working. I initially just wanted to use "char" but that doesn't work for some reason.
Visual Studio didn't like:
char test;
test = "help";
It underlined the "=".
For now, I just want to return a string value from a function. There's more that I need it to do, but this is the main issue right now.
Uncommenting the cout line actually does display the string. But not returning the string.
Your program both prints and returns the string, printing it again in main. The only problems I can see with your program are:
You are using system("pause") for no reason.
You are not consistent with the use of either the std:: prefix or importing the namespace. On this regard I highly suggest the std:: prefix.
You are not using the function argument.
I initially just wanted to use "char" but that doesn't work for some reason.
Well, char, as the name suggests, can only store 1 characters. In:
char test = "help";
you are trying to assign 5 characters (4 + \0) to an objects who's size can only store 1. That's the reason why your compiler complained.
I think you need to pass an int to your function and get it back in string form. To do this conversion you need something like this:
std::ostringstream stm;
stm << yourIntValue;
std::string s(stm.str());
or this:
char bf[100];
sprintf(bf, "%d", yourIntValue);
std::string s(bf);
If you put this snippet in a function then you can also accept an int parameter, convert it to a std::string and return the std::string as others have shown.
What you need to do is to declare return type of function as std::string and then return either a string object, something that can implicitly be converted to string object or something that explicitly constructs string object.
Example:
std::string foo(){
return "idkfa"; //return C-style string -> implicitly convertible to string
return {"idkfa"}; // direct initialization of returning std::string
return std::string("idkfa"); //return explicitly constructed std::string object
}
Also note that C-style strings are of type char* (C-style strings are basically an array of chars, with last element being \0, that is 0).
Your code works perfectly fine, though the the system("pause") is totally redundant and pointless and should be removed. It may in fact be confusing you.

How to change return type based on inner code? (string to number conversion)

For example, I have this code which converts from string to number:
#include <sstream>
template <typename T>
T string_to_num( const string &Text, T defValue = T() )
{
stringstream ss;
for ( string::const_iterator i=Text.begin(); i!=Text.end(); ++i )
if ( isdigit(*i) || *i=='e' || *i=='-' || *i=='+' || *i=='.' )
ss << *i;
T result;
return ss >> result ? result : defValue;
}
Problem is it requires two arguments, the second which gives it a clue as to what type of number I am returning (an int or a float etc.).
How can I make it so that if the string contains a decimal '.' it returns a decimal datatype (eg. float), otherwise an whole datatype (eg. int)?
Unless someone has a better code they can share to do this..?
The question is why you need this. I think you want it, just to get rid of indicating the type before calling string_to_num:
????? number = string_to_num<double>("123.21");
^^^^^
do_something(number);
But, you already are indicating the type by <double>. A simple syntax sugar, auto is what you want. (It's compile time)
Otherwise, you need a variant type, and it's far from your string_to_num definition. It has a lot of overhead.
You're code is already OK, and the output is based on T. So, in real programs you have no problem.

c++ accessing string index inside this pointer

class X
{
private:
string DATA;
.
.
.
const string read_entry( const string & s ) { return this->(DATA[1]); } //Error
}
What's wrong with this? I'm trying to access the index of the DATA string, but I get an error when I do this->DATA[1]
There are two issues in the code snippet:
Illegal () around DATA[1]. Change return this->(DATA[1]); to return this->DATA[1];.
Wrong return type: the type of DATA[1] is char, not string.
Also, add ; after class definition.
The problem appears to be the return type of the function. The stated type is const string but indexing into a string returns a char. Try the following instead
char read_entry( const string & s ) { return this->DATA[1]; }
A few things:
the return type of your function (const string) does not match the type you are returning (char). Without knowing the purpose of this function I don't know exactly what fix to make to this.
you're passing in a string& to your function, but it isn't used in the function body. What is the purpose of that?
you don't need the explicit reference to 'this', 'return DATA[1]' is sufficient.
unless you're very certain about the length of DATA, you should use DATA.at(1) rather than DATA[1], because .at() does a range check for you. Without this you might be risking memory problems.
in future, please explain what the code is supposed to do, so we can understand why it looks the way it does.