C++ function overload resolution - bool vs string [duplicate] - c++

This question already has an answer here:
String-bool comparsion - why?
(1 answer)
Closed 8 years ago.
I've found some unexpected behavior using the VC++2010 compiler with function overloading:
struct A {
A();
void O(const bool in); //(1)
void O(const std::string in);//(2)
}
Some of the following calls do not resolve like I would think:
A a;
a.O(true);//calls (1)
a.O("what?");//calls (1)
a.O(std::string("better..."));//calls (2)
Can someone explain to me why the second call resolves to the boolean function and what the motivation behind resolving in that way is?

The type of "what?" is char const[6], which after decaying to char const* while being passed into the function, is implicitly convertible to bool. The standard conversion takes precedence over user-defined implicit conversions, like the case of converting char const* to std::string.

Related

Function Overloading with const [duplicate]

This question already has answers here:
Why is this call to member function ambiguous?
(3 answers)
Closed 5 years ago.
struct A
{
void fn(double a) const {}
void fn(int a){}
};
int main()
{
A().fn(1.);
}
For the above mentioned function why does the compiler produce an ambiguity; Both the types are different.
Why would you like to pass an int only to a non-const A?
There are two parameters to each member function, this and a. So you require a const A* for this and doublefor a, or non-const A* and int.
And the call doesn't fully match either alternative, as you have non-const Aand double. So the compiler can either convert A() to const A, or doubleto int. And it cannot decide which is the best.

Why doesn't std::reference_wrapper implicitly cast to a reference when calling member function? [duplicate]

This question already has answers here:
How to correctly use std::reference_wrappers
(2 answers)
Closed 4 years ago.
I don't understand exactly why one cannot use a std::reference_wrapper like this:
#include <vector>
#include <functional>
struct Foo
{
void f() {};
};
int main()
{
std::vector<std::reference_wrapper<Foo>> vrFoo;
Foo foo;
vrFoo.push_back(foo);
// vrFoo[0].f(); // error
vrFoo[0].get().f(); // or static_cast<Foo&>(v[0]).f();
}
Why do we have to use the get() member function? It looks like std::reference_wrapper has an implicit conversion to T& via operator T&() const noexcept, see http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
so why isn't v[0] implicitly converted to a reference?
In other situations, such as
std::cout << v[0] << std::endl
this conversion takes place (I assume here that Foo overloads operator<<)
Because . is always used to access members of the object it's applied to. Type conversions aren't considered.
There's a proposal to allow overloading of operator., to enable exactly what you want, but that won't be standard until at least C++17, if at all.
This is a language limitation as #MikeSeymour pointed out.
And this is the reason why I think std::reference_wrapper should have an overloaded operator& that returns the address of the wrapped object:
template<class T>
struct reference_wrapper{
...
T* operator &(){return ptr;}
}
So that later one can use &Foo->f() or (*&Foo).f() instead of Foo.get().f() or static_cast<T&>(Foo).f().

Boost variant ambiguous construction [duplicate]

This question already has answers here:
boost::variant - why is "const char*" converted to "bool"?
(3 answers)
Closed 8 years ago.
The Boost Variant documentation says the following of the constructor that accepts arbitrary type:
template<typename T> variant(T & operand);
Requires: T must be unambiguously convertible to one of the bounded types (i.e., T1, T2, etc.).
The same is true of the constructors accepting const T& and T&&. So I expect that the following code won't compile:
boost::variant<std::string, bool> v = "text";
But the code compile, and v becomes a bool, which is something I definitely did not want. Of course the solution is to wrap the string literal in a std::string constructor. My question is:
Why does this code compile?
How does it choose the type (as const char* is convertible to both std::string and bool)?
Generally, user-defined conversions lose overload resolution process to standard conversions.
There is a built-in conversion from const char pointers to bool which is preferred over the non-built-in conversion from const char * to std::string (e.g. see Implicit conversions).
std::string, while part of the standard library, is not a built-in type so its conversion constructors are considered only after conversions to built-in types.
Some references:
Why does the compiler choose bool over string for implicit typecast of L""?
Why is my overloaded C++ constructor not called?

Overloading type cast operator, to cast to a pointer to function [duplicate]

This question already has answers here:
C++ Conversion operator for converting to function pointer
(6 answers)
Closed 8 years ago.
I'm having some difficulty, overloading the cast to pointer to function operator of a class. In code, what I want is this:
typedef int(*funcptrtype)(int);
struct castable {
operator funcptrtype() {return NULL;}
};
but I want to be able to do it without using the typedef. If you're curious, I need this, because pre-c++11 template aliases aren't available (so the typedef trick is not an option in templated contexts...)
I would normally expect this to work:
operator int(*)(int)() {return NULL;}
But it doesn't. The compiler (g++ 4.6.1) says:
error: ‘<invalid operator>’ declared as function returning a function
This works:
int (* operator()())(int){return 0;}
But you're actually overloading the operator() to return a function pointer :)
The standard says:
The conversion-type-id shall not represent a function type nor an
array type
But it doesn't say function pointer type (The first code snipplet works anyway...).
Does anyone know the right syntax w/o typedef?
The grammar doesn't allow this: the type in a conversion operator declaration is a type-specifier, not a type-id. You have to use a typedef or alias; in a template context, use the usual replacement:
template<typename T>
struct something {
typedef T (*type)(int);
};

Why exactly is this template function successfully compiling? [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Destructors of builtin types (int, char etc..)
Template Function:
template<typename T> void kill(T* type)
{
type->~T();
}
Call:
int x= 5;
kill(&x);
woah, it compiled!? How can a primitive type like int have a destructor? It is also working with char , bool etc.
§12.4.16 of the Standard says
16 [ Note: the notation for explicit call of a destructor can be used for any scalar type
name (5.2.4). Allowing this makes it possible to write code without having to know if a
destructor exists for a given type. For example,
typedef int I;
I* p;
p->I::~I();
—end note ]
The relevant part of the standard is §5.2.4/1:
The use of a pseudo-destructor-name after a dot . or arrow -> operator represents the destructor for the non-class type named by type-name. The result shall only be used as the operand for the function call operator (), and the result of such a call has type void. The only effect is the evaluation of the postfix expression before the dot or arrow.