default argument mismatch in C++? - c++

Consider the following code:
#include <iostream>
class Bar
{
public:
void foo(bool b = false, std::string name = "");
};
void Bar::foo(bool b, std::string name)
{
if (!b)
{
std::cout << "b is false" << std::endl;
}
else
{
std::cout << "b is true" << std::endl;
}
}
int main()
{
Bar myBar;
myBar.foo("bla");
return 0;
}
I guess C++ is not broken, but can anyone please explain why the output is true? I am working on VS 2010 but I also checked in ideone which runs gcc

The compiler is implicitly casting the first parameter, a char const[4], to bool, and results in true.
It's equivalent to
myBar.foo((bool)"bla");
which is also equivalent to
myBar.foo((bool)"bla", "");

Because the "bla" is a char const[4], which decays to const char*, and is cast to a bool. Since it's value is not 0, the cast takes the value true. A simpler example:
#include <iostream>
int main()
{
std::cout << std::boolalpha; // print bools nicely
bool b = "Hello";
std::cout << b << "\n";
}
produces
true

Bool parameter convert "bla" to true.
You need to change order of your parameters.

Related

Is it possible to expand a macro into two piece of data with different types

UPDATE
It seems that the original question is not that clear, so I made another example to specify what I need.
#define RPC_FUNC(X) &X,??? // I don't know how...
class Test {
public:
static void func(int a) {}
};
int main()
{
const auto ptr1 = std::make_pair(&Test::func, "Test::func");
// const auto ptr2 = std::make_pair(RPC_FUNC(Test::func));
// ptr2.first(123); // this should call the function Test::func
// std::cout << ptr2.second; // this should print the string "Test::func"
return 0;
}
How to define the macro RPC_FUNC to make this code work? Meaning that I want to make ptr1 and ptr2 exactly the same.
ORIGINAL
I want to do a piece of code like this:
template<typename F> // F is the type of some functions
void func(F f, const std::string& funcMark) {
// do something
}
I want to pass a non-static member function and a string into the function func.
Sometimes, the second parameter is just the name of the first one. Let's see an example:
namespace sp {
class Test {
public:
void doJob() {}
};
}
func(&sp::Test::doJob, "doJob");
What I'm trying to do is to do the call above like this: func(MY_MARCO(sp::Test::doJob)).
Meaning that, the macro MY_MACRO should do expand its parameter sp::Test::doJob into &sp::Test::doJob, "doJob".
The specification what the macro should precisely do is dim. The stringizing operator # can turn macro argument into string literal:
// example code what it does
#include <iostream>
#define YOUR_MACRO(X) X() << " from " << #X "()"
int foo() { return 42; }
int main() { std::cout << YOUR_MACRO(foo) << std::endl; }
That outputs
42 from foo()
Turning string literal into std::string is also trivial:
#include <iostream>
#include <string>
#define YOUR_MACRO(X) X() << " from " << std::string(#X "()")
int foo() { return 42; }
int main() { std::cout << YOUR_MACRO(foo) << std::endl; }
Works same. So where are you stuck?
UPDATE:
Specification is now lot better! But ... it
is basically same what I already posted that you should use stringizing operator # in macro:
#include <iostream>
#define RPC_FUNC(X) &X, #X
class Test {
public:
static void func(int a) {
std::cout << "called Test::func(" << a << ")" << std::endl;
}
};
int main() {
const auto ptr1 = std::make_pair(&Test::func, "Test::func"); // gets warning about unused variable
const auto ptr2 = std::make_pair(RPC_FUNC(Test::func));
ptr2.first(123); // prints "called Test::func(123)"
std::cout << ptr2.second << std::endl; // prints "Test::func"
return 0;
}

Types should be the same but are not

I am not sure I understand why the first test evaluates to true and the second to false. I know that the information from typeid().name() is usually not reliable, but my main problem is with the typeid itself. I don't understand why the type of *test is not Location<1>, or what else is wrong. Any thoughts? Is there same wrapper around a type here that I don't see? Thanks in advance, and apologies if the answer is obvious.
#include <iostream>
#include <utility>
#include <typeinfo>
class LocationAbstract
{
virtual void get_() = 0;
};
template<int i>
class Location : public LocationAbstract
{
public:
static constexpr int test = i;
virtual void get_() override
{
return;
}
};
template <int i>
Location<i> LocationGenerator()
{
Location<i> test{};
return test;
}
int main()
{
LocationAbstract *table[10];
table[0] = new decltype(LocationGenerator<0>());
table[1] = new decltype(LocationGenerator<1>());
Location<1> *test;
try
{
std::cout << "Casting\n";
test = dynamic_cast<Location<1>*>(table[1]);
}
catch (std::bad_cast &e)
{
std::cout << "Bad cast\n";
}
// test1, evaluates to true
std::cout << (typeid(*test) == typeid(*dynamic_cast<Location<1>*>(table[1]))) << "\n";
std::cout << typeid(*test).name() << "\n";
std::cout << typeid(*dynamic_cast<Location<1>*>(table[1])).name() << "\n----\n";
// test2, why does this evaluate to false while the above evaluates to true ?
std::cout << (typeid(Location<1>()) == typeid(*dynamic_cast<Location<1>*>(table[1]))) << "\n";
std::cout << typeid((Location<1>())).name() << "\n";
std::cout << typeid(*dynamic_cast<Location<1>*>(table[1])).name() << "\n";
auto test1 = Location<1>();
auto test2 = *dynamic_cast<Location<1>*>(table[1]);
std::cout << typeid(test1).name() << " and " << typeid(test2).name() << "\n";
return 0;
}
An extra set of () makes all the difference here. In typeid(Location<1>()) and typeid((Location<1>())), Location<1>() actually means two totally different things.
In typeid(Location<1>()), Location<1>() is interpreted as a function type that returns a Location<1> and takes no parameters.
In typeid((Location<1>())), Location<1>() is interpreted as value-initializing an anonymous Location<1> object.
The typeid operator can work on either types or expressions. That is, you can say typeid(int) as well as typeid(42). Since Location<1>() can be interpreted as a type, the language does so. (Location<1>()) cannot be interpreted as a type though, so it must be interpreted as an expression. The only thing Location<1>() can mean as part of an expression is to value-initialize an anonymous Location<1> object, so typeid gives you the type of that object.
Let this be yet another reason to prefer uniform-initialization syntax when creating temporary objects; Location<1>{} would not have this ambiguity.
Examine these two lines:
std::cout << (typeid(Location<1>()) == typeid(*dynamic_cast<Location<1>*>(table[1]))) << "\n";
std::cout << typeid((Location<1>())).name() << "\n";
In the first line, you use typeid(Location<1>()). typeid can take types as well as expressions, and Location<1>() is a function type with no parameters and a return type of Location<1>.
So why does the name print the same? That's because of the second line: typeid((Location<1>())). By wrapping the argument in parentheses, it is no longer a valid type, so it is treated as an expression and the name of typeid(Location<1>) is printed. Removing the extra parentheses prints F8LocationILi1EEvE under the same mangling scheme.
To avoid the ambiguity, you can also use the type directly (typeid(Location<1>)) or use braces: typeid(Location<1>{})).

Templates Default Arguments not working in C++

#include <iostream>
template<typename T = char>
T cast(T in){
return in;
}
int main(){
std::cout << cast<>(5) << std::endl;
return 0;
}
Above will print 5 instead of an empty character, as the function is supposed to return a character by default and not an int. What am I ding wrong?
Edit:
Forcing it with std::cout << cast<char>(5) << std::endl; shows an empty character.
The declaration of 5 is an integer by default. This causes 'T' to be overridden with the type int, rather than using your default type. If you really wanted the char of value 5 (which you probably don't), you could specify it as '\x5'.
For the ascii character 5....
int main(){
std::cout << cast('5') << std::endl;
return 0;
}
Default types in templates tend to be useful when it's not easy to determine the template type, e.g. cast from int
template<typename T = char>
T cast(int v){
return T(v);
}
and now this will default to a method that casts an int to a char (rather than a int to int).
std::cout << cast(53) << std::endl;

Program fails to call the specialized template implementation

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.

Why does std::is_const<const int&>::value evaluate to false?

This is a spin off of the question How to check if object is const or not?.
I was surprised to see the following program
#include <iostream>
#include <type_traits>
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_const<const int&>::value << "\n";
}
produced this output
false
In what context does it make sense to think of const int& as a non-const type?
Perhaps it'll be easier to understand with this example
std::cout << std::is_const<int const *>::value << "\n"; // pointer to const int
std::cout << std::is_const<int * const>::value << "\n"; // const pointer to int
Output:
false
true
The first type is a pointer to a const int, while in the second the int * itself is const. Hence it results in true while the former is false. Similarly, what you have a reference to a const int. If int& const were valid it'd result in true.
A const qualifier on a reference just means that the value can't be modified via the reference. It can still be modified by other means. For example:
int a = 1;
const int &b = a;
std::cout << b << std::endl; // Prints 1
a = 2;
std::cout << b << std::endl; // Prints 2
Thus, you can't assume that the value of a const reference is actually constant.