Can someone explain, why the output is "C" in this code?
#include <iostream>
using namespace std;
template<class X>
X maximum(X a,X b)
{
if(a > b)
return a;
else
return b;
}
int main() {
cout << maximum("C","D") << endl;
}
Note that in your case the type X will be inferred as const char*, hence you are comparing two const char *s i.e. the addresses of the two string literals.
If you want to get the expected result, use something like the following
cout << maximum("C"s, "D"s) << endl;
To pass std::strings instead of passing the addresses of the string literals.
See string literal operator
Demo
Or use characters instead of using string literals i.e 'C' and 'D' and in that case, X will be inferred as char.
And See Why is "using namespace std;" considered bad practice?
When you use maximum("C","D"), the template parameter is char const*. You end up comparing two pointers. There is no guarantee which pointer will be greater. You have indeterminate behavior.
If you want to compare the string "C" and string "D", you can use:
cout << maximum(std::string("C"), std::string("D")) << endl; // or
cout << maximum("C"s, "D"s) << endl; // or
cout << maximum<std::string>("C", "D");
If you want compare just the characters C and D, you should use
cout << maximum('C', 'D') << endl;
If you want this to work for cstring-literals also, add a specialization.
#include <cstring>
template<class X>
X maximum(X a, X b)
{
return a > b ? a : b;
}
template<>
char const* maximum<char const*>(char const* a, char const* b)
{
return std::strcmp(a, b) > 0 ? a : b;
}
Related
//libraries
#include <iostream>
//standard namepace
using namespace std;
int Car() {
int a;
int b;
cout << "Fuel Tank" << endl;
cin >> a;
cout << "MPG" << endl;
cin >> b;
return a, b;
}
int main() {
int a;
int b;
a,b = Car();
cout << "Print Values " << (a,b); // <--- Line 25
return 0;
}
Let's say you put 10 and 15 as the first and second input. Why is 15 the only variable to print in the cout statement on line 25.
That's not how C++ works.
You need:
std:: pair<int, int> Car() {
...
return {a, b};
}
auto [a, b] = Car();
std::cout << a << ", " << b;
What you have:
int Car()
Car is a function which returns 1 int.
return a, b;
Here you have the comma operator which evaluates every argument and discards all but the last one. So it returns b.
a, b = Car();
(a, b)
Again the comma operator. a is discarded and b is assigned. Then a is discarded and b is printed.
Unlike Python, C++ does not have a built in notion of a tuple. Your Car function is declared to return a single integer, and so one integer you will get. An alternative is to use std::pair<int, int> in #include <utility> like so:
std::pair<int, int> Car() {
// ...
return std::make_pair(a, b);
}
I assume the program compiles because in C/C++, the comma separated expression list as you wrote is evaluated in order and only the last expression or item in that list is returned. So your first Car() function returns the last integer b, and you only initialize b in your assignment in main() to that other b. Likewise, your cout only prints b, hence 15.
What I would recommend doing is making the function a void and passing the variables by reference. When you pass the variables by reference, you can change their value in the function and they will not be lost due to scope. This is because passing by reference references the location in memory where that variable is stored, instead of creating a copy like passing by value does (which you did).
#include <iostream>
using namespace std;
void car(int &a, int &b); // function prototype calling for a and b to be passed by
// reference
int main()
{
int a = 0;
int b = 0;
car(a, b);
cout << "Print Values " << a << " " << b;
return 0;
}
void car(int &a, int &b)
{
int temp = 0;
cout << "Fuel Tank" << endl;
cin >> a;
cout << "MPG" << endl;
cin >> b;
}
As you see, instead of returning values, the function changes the values of the variables by accessing their location.
Edit: Typically, functions will go below main and you have prototypes for the functions above main (as seen in my example).
Another thing, you named the function, "Car();". Typically, functions start with the first word as a lowercase letter with the following words capitalized. This makes it easier to not confuse them with constructor function names for classes, in which the first letter of the first word is usually capitalized.
I am trying to learn C++ template. While I run the following example, the program couldn't call the specialized template implementation. Therefore, I got the wrong output. Could anybody tell why?
template <class T>
T max(T a, T b)
{
cout << "2 ..." <<endl;
return a > b ? a : b;
}
template<>
char* max(char* a, char* b)
{
cout << "1 ..." <<endl;
return strcmp(a, b) > 0 ? a : b;
}
int main()
{
cout << max("Aladdin", "Jasmine") << endl;
return 0;
}
The arguments are passed as constant char. Therefore, try the following code instead. Note that I also included the necessary header file includes. Moreover, it is highly advisable to use std::cout, or use using std::cout;.
#include <iostream>
#include <cstring>
template <class T>
T max(T a, T b)
{
std::cout << "2 ..." << std::endl;
return a > b ? a : b;
}
template<>
const char* max(const char* a, const char* b)
{
std::cout << "1 ..." << std::endl;
return std::strcmp(a, b) > 0 ? a : b;
}
int main()
{
std::cout << max("Aladdin", "Jasmine") << std::endl;
return 0;
}
The reason you're seeing the issue is that the arguments you're passing are of type char const * (also can be spelled const char *). There isn't any standard way that I know of in C++ to print out the full name of a type. But there is a way to test this sort of thing..
One of the problems of templates is that the system will expand any templates it can. And so you will have code mysteriously work a certain way and not be completely sure why. One way you could've gotten the compiler to tell you exactly what the problem was in this case was to try to remove the template:
#include <iostream>
#include <cstring>
using ::std::cout;
using ::std::strcmp;
char* max(char* a, char* b)
{
cout << "1 ..." << '\n'; // Don't use ::std::endl Use cerr if you need flushing.
return strcmp(a, b) > 0 ? a : b;
}
int main()
{
cout << max("Aladdin", "Jasmine") << '\n';
return 0;
}
The compiler would've helpfully told you that you were trying to call a function that took non-const arguments with const arguments, and you would've learned exactly what the problem was.
I was just modifying an old example of my code by adding a digit separator to a user-defined literal, parsed by a variadic template:
namespace lits {
// helper for 1 arg
template<char C> int bin(); // common
template<> int bin<'1'>() { return 1; } // spec.
template<> int bin<'0'>() { return 0; } // spec.
// helper 2 or more args
template<char C, char D, char... ES>
int bin() {
return bin<C>() << (sizeof...(ES)+1) | bin<D,ES...>() ;
}
// operator"" _bin
template<char...CS> int operator"" _bin()
{ return bin<CS...>(); };
}
int main() {
using namespace lits;
int number = 1000'0000_bin; // <<< I added a ' here
}
Boy, was I surprised when by g++6.2.0 tried to instantiate bin<'\''>. It tried to pass the ' as a char to my template template<char...CS> int operator"" _bin()! I tried it with clang++-3.9 and msvc++-19.00, same complaint, which really makes me sceptical.
I have the feeling that that may not the right behavior. I would have understood it if my literal was in quotes, say "1000'0000"_bin, but this form does not exist for template operator"", right?
Am I to expect the digit separator ' in my template user-literal operators, too, now?
Update 1: in case the ' is ok:
One could use the digit-sep as a sep for all sort of things, say, complex numbers. Would the behavior of `52.84'67.12_i' for 52.84+67.12i be well defined?'
Udpdate 2: As reaction some of the comments. The following compiles:
#include <iostream>
#include <string>
using std::string;
namespace lits {
// helper
template<char C> string sx() { return string{}+C; }
// helper 2 or more args
template<char C, char D, char... ES>
string sx() {
return sx<C>() + sx<D,ES...>();
}
// operator"" _sx
template<char...CS> string operator"" _sx()
{ return sx<CS...>(); };
}
int main() {
using namespace lits;
std::cout << 10000000_sx << '\n';
std::cout << 10'000'000_sx << '\n';
std::cout << 0x00af_sx << '\n';
std::cout << 0x0'c'0'a'f_sx << '\n';
std::cout << 007_sx << '\n';
std::cout << 0b01_sx << '\n';
// the following do not work:
//std::cout << 0b0a8sh3s1_sx << '\n';
//std::cout << "abcde"_sx << '\n';
}
And the output is:
10000000
10'000'000
0x00af
0x0'c'0'a'f
007
0b01
Which means that the template gets all the characters: prefixes and digit separators -- all of them. (g++-6.2.0)
As #krzaq's answer suggests, it seems this is the plan of the Std, so one can rely on it.
As far as I can tell, yes. As explained here, digit separators are legal members of user defined integer literals.
And the template integer literal is defined as:
N4140 § 2.13.8 [lex.ext] / 3
Otherwise (S contains a literal operator template), L is treated
as a call of the form
operator "" X <’c1’, ’c2’, ... ’ck’>()
where n is the source character sequence c1c2...ck. [ Note: The sequence
c1c2...ck can only contain characters
from the basic source character set. —end note ]
There's not a word about removing separators.
As much as I read here the separator is allowed only when you get the literal as a number, not when the operator is a raw literal. That means you will get rid of the separator by the compiler if the operator parameter type is unsigned long long, not if it's one of the raw ones that get C-string or char.
I am trying to see what happens when we compare strings directly using operators like <, >, etc. The two usages in the code below surprisingly give different answers. Aren't they exactly same way of saying things?
#include <iostream>
template <class T>
T max(T a, T b)
{
//Usage 1:
if (a > b) return a; else return b;
//Usage 2:
return a > b ? a : b ;
}
int main()
{
std::cout << "max(\"Alladin\", \"Jasmine\") = " << max("Alladin", "Jasmine") << std::endl ;
}
Usage 1 gives "Jasmine" while usage 2 gives "Alladin".
When you use:
max("Alladin", "Jasmine")
it is equivalent to using:
max<char const*>("Alladin", "Jasmine")
In the function, you end up comparing pointers. The outcome of the call will depend on the values of the pointers. It is not guaranteed to be predictable.
Perhaps you want to use:
max(std::string("Alladin"), std::string("Jasmine"))
or
max<std::string>("Alladin", "Jasmine")
Be warned that some compiler might pick up std::max when you use that. You may want to change max to my_max or something like that.
You are not actually comparing the string in your code. "Alladin" and "Jasmine" are actually of the type const char[] and they decay into pointers when you call max("Alladin", "Jasmine"). This means that in your function you are comparing the address of the strings and not the contents.
If you meant to test std::strings then you need to create std::strings and pass them to your max function.
Both methods are wrong. Character strings don't have valid > operator.
You can compare std::string instead:
#include <iostream>
#include <string>
template <class T>
T my_max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
std::string a = "Alladin";
std::string b = "Jasmine";
std::cout << "my max: " << my_max(a, b) << std::endl;
//standard max function:
std::cout << "standard max: " << max(a, b) << std::endl;
}
The expected result should always be "Jasmine"
I have an std::unordered_set that is supposed to store pointers to values stored in an std::list. The values are first added to the list, then their pointers are inserted into the set. The set uses a predicate that compares the values the pointers point to instead of the addresses. This produces undefined behavior.
Here's a minimal working example:
#include <unordered_set>
#include <iostream>
#include <string>
#include <list>
using namespace std;
template<typename T> struct set_hash {
size_t operator()(const T* p) const noexcept {
return reinterpret_cast<uintptr_t>(p);
}
};
template<typename T> struct set_eq {
bool operator()(const T* a, const T* b) const noexcept {
std::cout << "*a["<<*a<<"] == *b["<<*b<<"] "
<< boolalpha << (*a == *b) << std::endl;
return *a == *b;
}
};
template<typename T> using set_t =
std::unordered_set<const T*, set_hash<T>, set_eq<T>>;
int main()
{
set_t<string> set;
list<string> list{"a", "b", "a", "c", "a", "d"};
for (auto& str : list) {
set.insert(&str);
cout << str << ' ';
}
cout << endl;
for (auto p : set) cout << *p << ' ';
cout << endl;
string c("c");
cout << **set.find(&c) << endl;
return 0;
}
After running the program multiple times I get three possible outputs:
a b a c a d
d a c a b a
Segmentation fault
a b a c a d
d a c a b a
*a[c] == *b[a] false
Segmentation fault
a b a c a d
d a c a b a
*a[c] == *b[c] true
c
The output I expect is
a b a c a d
a b c (not necessarily in this order)
c
with some lines like *a[c] == *b[c] true, depending on how many times the predicate is called.
I do not understand what results in undefined behavior.
I get identical results with gcc4.8.2, gcc4.9.1, and gcc4.9.2.
The problem is that the hash function hashes the pointers while the comparison function compares the values pointed at by the pointers. So if you have two different list elements with the same value, the hash function will give different hashes (from the pointers), while the comparison function will compare equal.
The hash function needs to be consistent -- it needs to hash the values instead of the pointers.