Boost variant ambiguous construction [duplicate] - c++

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?

Related

c++: implicit conversion order

I've a (member-)fuction overloaded like this:
bool foo(bool);
int foo(int);
float foo(float);
...
std::string foo( std::string const&);
for a couple of build-in-types but not for const char*. Calling foo("beauty is only skin-deep");, to my big suprise, called the bool-variant of the foo function. This leads to my questions:
QUESTION: Is there a well defined implicit conversion order for build-in-types
NOT THE QUESTION: How to avoid implicit conversion. How evil is implicit conversion. ...
EDIT: removed question about implicit converstion order for user-defined-questions
according to: http://en.cppreference.com/w/cpp/language/implicit_cast
all build-in conversions take place before user defined ones
pointer -> bool is a 'Boolean conversions' (needed for if(pointer) notation), last of 'numeric conversions'
'const char*' -> std::string is a 'user defined conversion' as from language point of view, std::string is a user defined type.
Unfortunately simplest solution is to write proper overload of fun(const char*), or to avoid fun(bool) vs fun(std::string) overloads

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

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.

How come an user defined conversion is a better match than a standard integer conversion?

You can find the text below in Appendix B of the book "C++ Templates The Complete Guide" by David Vandevoorde and Nicolai Josuttis.
B.2 Simplified Overload Resolution
Given this first principle, we are left with specifying how well a
given argument matches the corresponding parameter of a viable
candidate. As a first approximation we can rank the possible matches
as follows (from best to worst):
Perfect match. The parameter has the type of the expression, or it has a type that is a reference to the type of the expression (possibly
with added const and/or volatile qualifiers).
Match with minor adjustments. This includes, for example, the decay of an array variable to a pointer to its first element, or the
addition of const to match an argument of type int** to a parameter of
type int const* const*.
Match with promotion. Promotion is a kind of implicit conversion that includes the conversion of small integral types (such as bool,
char, short, and sometimes enumerations) to int, unsigned int, long or
unsigned long, and the conversion of float to double.
Match with standard conversions only. This includes any sort of standard conversion (such as int to float) but excludes the implicit
call to a conversion operator or a converting constructor.
Match with user-defined conversions. This allows any kind of implicit conversion.
Match with ellipsis. An ellipsis parameter can match almost any type (but non-POD class types result in undefined behavior).
A few pages later the book shows the following example and text (emphasis mine):
class BadString {
public:
BadString(char const*);
...
// character access through subscripting:
char& operator[] (size_t); // (1)
char const& operator[] (size_t) const;
// implicit conversion to null-terminated byte string:
operator char* (); // (2)
operator char const* ();
...
};
int main()
{
BadString str("correkt");
str[5] = 'c'; // possibly an overload resolution ambiguity!
}
At first, nothing seems ambiguous about the expression str[5]. The
subscript operator at (1) seems like a perfect match. However, it is
not quite perfect because the argument 5 has type int, and the
operator expects an unsigned integer type (size_t and std::size_t
usually have type unsigned int or unsigned long, but never type int).
Still, a simple standard integer conversion makes (1) easily viable.
However, there is another viable candidate: the built-in subscript
operator. Indeed, if we apply the implicit conversion operator to str
(which is the implicit member function argument), we obtain a pointer
type, and now the built-in subscript operator applies. This built-in
operator takes an argument of type ptrdiff_t, which on many platforms
is equivalent to int and therefore is a perfect match for the argument
5. So even though the built-in subscript operator is a poor match (by user-defined conversion) for the implied argument, it is a better
match than the operator defined at (1) for the actual subscript! Hence
the potential ambiguity.
Note that the first list is Simplified Overload Resolution.
To remove the "possibly" and "potential" about whether or not int is the same as ptrdiff_t, let's change one line:
str[(ptrdiff_t)5] = 'c'; // definitely an overload resolution ambiguity!
Now the message I get from g++ is:
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
and --pedantic-errors promotes that warning to an error.
So without diving into the standard, this tells you that the simplified list is only part of the story. That list tells you which of several possible routes to prefer when going from A to B, but it does not tell you whether to prefer a trip from A to B over a trip from C to D.
You can see the same phenomenon (and the same g++ message) more obviously here:
struct S {
explicit S(int) {}
operator int() { return 0; }
};
void foo(const S&, long) { }
void foo(int, int) { }
int main() {
S s(0);
foo(s, 1);
}
Again the call to foo is ambiguous, because when we have a choice of which argument to implicitly convert in order to choose an overload, the rules don't say, "pick the more lightweight conversion of the two and convert the argument requiring that conversion".
Now you're going to ask me for the standard citation, but I shall use the fact I need to hit the hay as an excuse for not looking it up ;-)
In summary it is not true here that "a user defined conversion is a better match than a standard integer conversion". However in this case the two possible overloads are defined by the standard to be equally good and hence the call is ambiguous.
str.operator[](size_t(5));
Write code in definite way and you'll not need to bother about all this stuff :)
There is much more to thing about.

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);
};

What does the C++ standard say about the difference between casting from type a to type b, and instantiating/Constructing type b? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference between (type)value and type(value)?
If you have a function that takes an argument of type b, but at the call site you only have a variable of type a. Is there a difference between casting the function parameter from a to b, and constructing type b.
The specific example I am interested in is when there is no user defined cast operator, but there is a single argument constructor.
Example:
Function definition:
void DoWork(const B &arg1);
In my specific example type a is const char *
Call site:
DoWork((B)"Hello");
vs
DoWork(B("Hello"));
B class definition
class B
{
public:
B() : m_szValue(){}
B(const char *szValue) { strcpy (m_szValue, szValue); }
private:
char m_szValue[MAX_VALUE_LEN + 1];
};
Writing a C-style cast (T)x, where x is of type U, more or less tries the following in order:
If T and U are of class type, look for a conversion operator U::operator T() const or a one-argument constructor T::T(U).
If T and U are primitive types, apply the standard value conversions (int to double, etc.).
reinterpret_cast<T>(x).
Note that you mustn't have both a conversion operator and implicit conversion construction, though, or the call will be ambiguous.
[Correction/Clarification:] There is no difference between T(x) and (T)x.[/] You can even say DoWork("Hello"); on account of the implicit conversion provided by the one-argument constructor. (Do disallow this sneaky behaviour, declare the constructor explicit, as is often a good idea for one-argument constructors.)