I'm currently trying to debug a piece of simple code and wish to see how a specific variable type changes during the program.
I'm using the typeinfo header file so I can utilise typeid.name(). I'm aware that typeid.name() is compiler specific thus the output might not be particularly helpful or standard.
I'm using GCC but I cannot find a list of the potential output despite searching, assuming a list of typeid output symbols exist. I don't want to do any sort of casting based on the output or manipulate any kind of data, just follow its type.
#include <iostream>
#include <typeinfo>
int main()
{
int a = 10;
cout << typeid(int).name() << endl;
}
Is there a symbol list anywhere?
I don't know if such a list exists, but you can make a small program to print them out:
#include <iostream>
#include <typeinfo>
#define PRINT_NAME(x) std::cout << #x << " - " << typeid(x).name() << '\n'
int main()
{
PRINT_NAME(char);
PRINT_NAME(signed char);
PRINT_NAME(unsigned char);
PRINT_NAME(short);
PRINT_NAME(unsigned short);
PRINT_NAME(int);
PRINT_NAME(unsigned int);
PRINT_NAME(long);
PRINT_NAME(unsigned long);
PRINT_NAME(float);
PRINT_NAME(double);
PRINT_NAME(long double);
PRINT_NAME(char*);
PRINT_NAME(const char*);
//...
}
Related
The following code has different compile results. From the error message I'm receiving it seems there's a confusion about operators precedence () and <<. I can easily overcome this issue by using a function. However I would like to understand and to know:
a) Which compiler it's evaluating correctly the expression? MSVC2017 seems more logical to me.
b) Is there an workaround still using MACROs?
Full sample code I used.
#include <cstdlib>
#include <typeinfo>
#include <sstream>
#include <iostream>
#ifndef NDEBUG
#define EXPR_INSPECT(param_)\
( (std::ostringstream{} << "< " #param_ " [" << typeid(param_).name() << "] > : " << param_).str() )
#else
#define EXPR_INSPECT(param_)\
(param_)
#endif //NDEBUG
int main(int argc, char *argv[])
{
auto ull_x {99LLU};
std::string string_x {"Checking..."};
std::cout << EXPR_INSPECT( ull_x) << std::endl;
std::cout << EXPR_INSPECT(string_x) << std::endl;
return EXIT_SUCCESS;
}
MSVC2017 works perfectly!
G++ 8.2.0 (MSYS2/MINGW) issues the following error: 'std::basic_ostream::__ostream_type' {aka 'class std::basic_ostream'} has no member named 'str' Attempts to call str() on ostream instead of ostringstream.
EDIT:
The problem here can also be reproduced by clang using Wandbox. Here is a minimal example:
#include <sstream>
#include <iostream>
int main()
{
auto s = std::ostringstream{};
decltype(((std::ostringstream{}) << "< "))::nothing;
decltype((s << "< "))::nothing;
}
In wandbox, clang found the second type std::basic_ostream, while the first type std::basic_ostringstream. That's very strange.
I recently finished a course on C++, to test to see what I knew from it I decided to start work on a operating system simulation, it seemed to be going fairly well up till I tried to implement a multiple users system by using a array to store user names, from which the user will select one and it will go into their user. However the problem with it that when I try and modify the array in the header file in the source file the program crashes.
header files:
#ifndef UBUNTU_LOGIN_H
#define UBUNTU_LOGIN_H
#include "Ubuntu_UserDetails.h"
#include <iostream>
#include <string>
#include <vector>
class Ubuntu_Login: protected UserDetails
{
public:
void Ubuntu_UserCreation();
void Ubuntu_login();
};
#endif // UBUNTU_LOGIN_H
#ifndef UBUNTU_USERDETAILS_H
#define UBUNTU_USERDETAILS_H
#include "Ubuntu_login.h"
#include <string>
#include <vector>
class UserDetails
{
protected:
std::string username;
std::string password;
std::string users[0];
};
#endif // UBUNTU_USERDETAILS_H
source files:
#include "Ubuntu_login.h"
#include "Ubuntu_UserDetails.h"
#include <iostream>
#include <vector>
#include <string>
void Ubuntu_Login::Ubuntu_UserCreation()
{
std::cout << "\t _____________" << std::endl;
std::cout << "\t|Create a user|\n" << std::endl;
std::cout << "Enter a username:" << std::endl;
std::getline(std::cin, username);
std::cout << "Enter a password:" << std::endl;
std::getline(std::cin, password);
users[0] = username;
std::cout << users[0] << std::endl;
std::cout << "User created successfully" << std::endl;
}
void Ubuntu_Login::Ubuntu_login()
{
std::cout << "\t ______" << std::endl;
std::cout << "\t|Log in|\n" << std::endl;
std::cout << "Select user" << std::endl;
}
#include "Ubuntu_login.h"
#include <iostream>
int main()
{
Ubuntu_Login UO;
UO.Ubuntu_UserCreation();
UO.Ubuntu_login();
}
when I try to run it I get as far as the initial password entry then the program crashed, I assume this is due to a stack overflow, but I wouldn't know how to solve it. Any help on solving this issue would be greatly appreciated as well as general help on the code as a whole :) .
also the reason I have not included things like storing passwords as hashes or not echoing the password is simply because I don't know the syntax to do it and I wanted to try to do the things I knew how to do first then add additional features later, so don't expect great code :P
Use std::vector<std::string> users
And then just users.push_back(username) to it. Dynamic array is suitable here.
In your Ubuntu_UserDetails.h you have this data member in the UserDetails class:
std::string users[0];
Then in a source file, you have this assignment:
users[0] = username;
If you access an item in an array with index 0, the array must have at least one element. In fact, index 0 refers to the first item in the array.
So, the users array should be defined as having some bigger size.
But, much better, consider using a convenient C++ container class for vectors, like std::vector.
So, in your header file, you can define a data member like this:
// Instead of:
// std::string users[0]
//
std::vector<std::string> userNames; // probably better than "users"
Then you can add new items to the vector using its push_back or emplace_back methods.
This is a question regarding the default global namespace in C++. I have the following code that compiles and runs properly using g++ clang-500.2.79.
#include <string>
#include <iostream>
using std::string;
using std::endl;
using std::cout;
bool is_palindrome(const string& str){
return equal(str.begin(), str.end(), str.rbegin());
}
int main(){
cout << "Hello is a palindrome: " << is_palindrome("Hello") << endl;
cout << "madam is a palindrome: " << is_palindrome("madam") << endl;
return 0;
}
My questions is, why does this code compile properly? I forgot to put #include <algorithm> and using std::equal at the beginning of my file. So the expected behaviour is for the compiler to complain.
The example at http://en.cppreference.com/w/cpp/algorithm/equal confirms that I should be using std::equal.
To investigate this further, I tried to track down exactly which version of the equal() function was being called. Being a relative newbie to C++ I don't know exactly how to do this either. I tried,
cout << "The function is: " << equal << endl;
Which generated a compiler error with some interesting information:
/usr/include/c++/4.2.1/bits/stl_algobase.h:771:5:
note: 'std::equal' declared here
Try as I might, I can't find information about stl_algobase (or more probably, I most likely don't understand what I've found). Is stl_algobase a set of functions that are automatically included in the global namespace?
A further questions is: What is the proper way to track (code or otherwise) down which function is being called when you are dealing with potentially overloaded or template functions in C++?
equal is in the std namespace. What you are seeing is argument dependent lookup (ADL). Because the arguments are in the std, the name lookup for equal considers that namespace too.
Here's a simplified example:
namespace foo
{
struct Bar {};
}
namespace foo
{
void bar(const Bar&) {}
void bar(int) {}
}
int main()
{
foo::Bar b;
foo::bar(b); // OK
bar(b); // ADL, OK
foo::bar(42); // OK
bar(42); // No ADL: error: 'bar' was not declared in this scope
}
Could any one help me to figure out which the following code cannot build successfully:
#include <iostream>
int main(void){
std::string str1("sfsfasfdsdf");
std::cout << str1 << std::endl;
return 1;
}
Thanks.
You have to include std::string header:
#include <string>
EDIT: According to #ShafikYaghmour's comments, include iostream sometimes brings in string, but it may not be the case for you if you only have the posted code.
I have tried to write the following code into my compiler and compile it:
#include <iostream>
#include <bitset>
using namespace std;
void binary(int a)
{
cout << bitset<8>(a).to_string() << endl;
}
int main()
{
binary(16);
system("pause");
return 0;
}
It should give me a binary output but I keep getting an error:
In function `void binary(int)':
no matching function for call to `std::bitset<8u>::to_string()'
I am new to C++ and dont really know what this means, please help me.
I think older versions of bitset::to_string<T>() takes a template argument. So this should work:
cout << bitset<8>(a).to_string<char>() << endl;
bitset don't have a to_string method (stl does not use to_string anyway). You should iterate on values yourself.