Overloaded Parenthesis operator with no arguments feature name - c++

Wikipedia's article on Properties presents a template class that can be used to create property members (lightly edited):
template <typename T> class property {
T value;
public:
T & operator = (const T &i) {
return value = i;
}
operator T const & () const {
return value;
}
};
struct Bar {
// Using the property<>-template.
property <bool> alpha;
property <unsigned int> bravo;
};
int main () {
Bar bar;
bar.alpha = true;
return bar.bravo;
}
What I'm trying to figure out is the name of the C++ feature that lets that to bar.bravo exist with no trailing ().
The code compiles fine... I just have no idea why!
Googling points me to 'Functors', but those overloaded parens operators all seem to have arguments (and I can understand how they work).

This:
operator T const & () const {
return value;
}
Is an overloaded conversion operator. Because it is not explicit, it allows for an implicit conversion.

The class property<T> defines an "implicit conversion to T const &" operator:
operator T const & () const { return value; }
So you can convert a value of type property<T> to a value of type T (more specifically, to a constant lvalue of type T).

Related

C++: using class with explicit operator bool overloaded

Context:
I have a class with an internal boolean value that seems like a good candidate for overloading operator bool, like this:
class MyBool{
private:
bool value_ = false;
// Nice API and logic to set the interal value_ to true or false...
public:
explicit operator bool() const {
return value_;
};
};
From https://en.cppreference.com/w/cpp/language/implicit_conversion, "Contextual conversions" section, this works in:
the controlling expression of if, while, for;
the operands of the built-in logical operators !, && and ||;
the first operand of the conditional operator ?:;
the predicate in a static_assert declaration;
the expression in a noexcept specifier;
Which explains why I get errors when trying to use it in other ways, like this:
MyBool x;
///...
bool y = x; // --> error: cannot convert ‘MyBool’ to ‘bool’ in initialization
// or:
bool z;
z = x; // --> error: cannot convert ‘MyBool’ to ‘bool’ in assignment
// Or returning from a function:
bool func(...){
MyBool x;
// ...
return x; // --> error: cannot convert ‘MyBool’ to ‘bool’ in return
}
// Or in Gtests, like:
MyBool x;
// ...
EXPECT_TRUE(x); // --> error: no matching function for call to ‘testing::AssertionResult::AssertionResult(MyBool)’
If I removed the explicit keyword, some problems cold arise because of implicit conversions (safe bool idiom in pre C++11: http://blog.asymptotic.co.uk/2014/03/the-safe-bool-idiom-in-c/).
In these cases, I could explicitly cast the MyBool variable to bool and it would work, but to me, this non-homogeneous use kind of defeats the purpose of overloading the operator, that is: to be able to naturally use MyBool as a bool. Instead, I could add a member function like this:
bool get_value() const {
return value_;
}
And use x.get_value() every time I need to "cast" to bool, even in the conditions, loops, etc.
The question is: is there a way to use this class in the cases above, or some of them, with modifications to the class code only (not the calling code), and without removing the explicit keyword?
(Preferrably in C++11).
The question seems to be how to both (1) have implicit conversion to bool and (2) avoid integer promotion/conversion. Delete the conversion to int:
class MyBool
{
public:
operator bool() const
{
return value_;
};
operator int() const = delete;
private:
bool value_ = false;
};
All of the lines in the question now compile because implicit conversion is allowed. And none of the safe-bool problems compile because integer conversion is deleted:
MyBool x;
int i = x;
x << 1;
x < 1;
C++20 version of deleting all the conversion operators that would in turn implicitly convert to bool:
#include <concepts>
class MyBool
{
private:
bool value_ = false;
public:
explicit operator bool() const { return value_; };
template <std::convertible_to<bool> T>
operator T() = delete;
};

Why is implicit conversion not ambiguous for non-primitive types?

Given a simple class template with multiple implicit conversion functions (non-explicit constructor and conversion operator), as in the following example:
template<class T>
class Foo
{
private:
T m_value;
public:
Foo();
Foo(const T& value):
m_value(value)
{
}
operator T() const {
return m_value;
}
bool operator==(const Foo<T>& other) const {
return m_value == other.m_value;
}
};
struct Bar
{
bool m;
bool operator==(const Bar& other) const {
return false;
}
};
int main(int argc, char *argv[])
{
Foo<bool> a (true);
bool b = false;
if(a == b) {
// This is ambiguous
}
Foo<int> c (1);
int d = 2;
if(c == d) {
// This is ambiguous
}
Foo<Bar> e (Bar{true});
Bar f = {false};
if(e == f) {
// This is not ambiguous. Why?
}
}
The comparison operators involving primitive types (bool, int) are ambiguous, as expected - the compiler does not know whether it should use the conversion operator to convert the left-hand template class instance to a primitive type or use the conversion constructor to convert the right-hand primitive type to the expected class template instance.
However, the last comparison, involving a simple struct, is not ambiguous. Why? Which conversion function will be used?
Tested with compiler msvc 15.9.7.
According to [over.binary]/1
Thus, for any binary operator #, x#y can be interpreted
as either x.operator#(y) or operator#(x,y).
According to this rule, in the case of e == f, the compiler can only interpret it as e.operator==(f), not as f.operator==(e). So there is no ambiguity; the operator== you defined as a member of Bar is simply not a candidate for overload resolution.
In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.
Operator overloads implemented as member functions don't allow for implicit conversion of their left-hand operand, which is the object on which they are called.
It always helps to write out the explicit call of an operator overload to better understand exactly what it does:
Foo<Bar> e (Bar{true});
Bar f = {false};
// Pretty explicit: call the member function Foo<Bar>::operator==
if(e.operator ==(f)) { /* ... */ }
This can't be confused with the comparison operator in Bar, because it would require an implicit conversion of the left-hand side, which is impossible.
You can trigger an ambiguity similar to the ones you see with the built-in types when you define Bar and its comparison operator like this:
struct Bar { bool m; };
// A free function allows conversion, this will be ambiguous:
bool operator==(const Bar&, const Bar&)
{
return false;
}
This is nicely demonstrated and explained in Scott Meyers's Effective C++, Item 24.

Implicit conversion from user-defined type to primitive type in C++

I am able to find plenty of information about implicit conversion from, say, an int to a user defined type. i.e. if a constructor takes an int as its parameter and is not prefaced by "explicit" then implicit conversions can occur.
What if I want my class to implicitly convert to an int?
For example, what function needs to be added either inside or outside of SimpleClass such that the main function will compile and output "1" to the console? (see comments)
#include <iostream>
class SimpleClass
{
private:
int m_int;
public:
SimpleClass(int value)
: m_int(value) {}
};
int main(int argc, const char * argv[])
{
SimpleClass simpleclass(1);
int i = simpleclass; // does not complile
std::cout << i << std::endl; // should output "1" to the console
return 0;
}
Implicit conversions can be defined in two ways:
non-explicit single-argument constructor.
non-explicit conversion function (a.k.a. conversion operator), N3337 12.3.2
The later allows defining conversion from class type to primitive type. Just add
class SimpleClass {
// ...
operator int() const;
};
SimpleClass::operator int() const
{
return m_int;
}
The technical.
Conversion to (almost) any type T can be performed by an operator T member function.
It is by default invoked implicitly, and if you declare it const it can also be invoked on a const object.
Thus:
struct MyType
{
operator int() const { return 1; }
};
Problems…
Having a an implicit conversion to basic type allows free play for all the built-in operators, including
Arithmetic operators.
Boolean operators.
Relational operators.
So you better make sure that all this works the way you want.
And that can be a lot of work!
There are also potential problems with overload resolution for calls involving instances of your type.
In short, implicit conversion to int, or pointer, or any built-in type, usually costs more than it's worth.
An exception where it can be worthwhile is when a class is used a lot, in a library.
What you can do about it.
Avoid implicit conversion, but do offer explicit conversion.
The best general explicit conversion is, IMHO, a named member function.
An alternative is an operator T prefixed with the keyword explicit, which is supported for this use in C++11 and later (in C++03 it could only be used on constructors).
If you want output via << to behave as if an implicit conversion is performed, then just define an operator<<.
And similarly for other situations where an implicit conversion would appear to be a general solution: just define what's appropriate for that specific situation, and avoid introducing a general implicit conversion.
To provide implicit conversion to a built-in type and yet avoid the “free for all” for built-in operators, you can use a templatized type conversion, e.g. like this:
#include <iostream>
template< class A, class B > struct Is_t_;
template< class Type > struct Is_t_<Type, Type> { using T = void; };
template< class A, class B >
using If_is_ = typename Is_t_<A, B>::T;
struct Bad_string
{
operator const char* () const { return "666!"; }
Bad_string( char const* = 0 ) {}
};
auto operator==( Bad_string const&, Bad_string const& )
-> bool
{ return true; }
struct Good_string
{
template< class Type, class Enabled_ = If_is_<const char*, Type>>
operator Type() const { return "42 :)"; }
Good_string( char const* = 0 ) {}
};
auto operator==( Good_string const&, Good_string const& )
-> bool
{ return true; }
#if defined( DO_GOOD )
using String = Good_string;
#elif defined( DO_BAD )
using String = Bad_string;
#else
# error "Define either DO_GOOD or DO_BAD, please."
#endif
auto main() -> int
{
String a, b;
(void) (a == "alfalfa"); // Errs for Bad_string
(void) (a + 1); // Compiles for Bad_string.
}
Ironically, when DO_GOOD is defined this code crashes the Visual C++ 2015 update 1 compiler, a so called “ICE” (Internal Compiler Error).
A workaround for that compiler is to instead define If_is_ as
template< class A, class B >
using If_is_ = std::enable_if_t< std::is_same<A, B>::value >;
To allow your class to be converted to an int, implement
operator int() const
{
return m_int;
}

how does operator overload resolution work based on return type in the following code of c++

I know that there is no legal overload based on return type in C++; i.e.
you cannot do something like:
int operator ++ getOwner();
char operator ++ getOwner();
However, I stumbled upon the following:
https://stackoverflow.com/a/9569120/1376317
class Proxy
{
My const* myOwner;
public:
Proxy( My const* owner ) : myOwner( owner ) {}
operator int() const
{
return myOwner->getInt();
}
operator char() const
{
return myOwner->getChar();
}
};
My question is how does operator overload work in this configuration. How do you call this in your main.cpp to get this kind of overloading. How does the compiler deduce , how to call the right overload?
My question is how does operator overload work in this configuration.
These operators provide implicit conversions. That means that this class can be used in many contexts where an int or char is expected, and will use these operators to provide the expected value.
How do you call this in your main.cpp to get this kind of overloading.
Here are a few examples of implicit conversions:
Proxy p = whatever();
int i = p; // convert to int
char c = p; // convert to char
long l = p; // ERROR: ambiguous
void f(int);
f(p); // convert to int
void g(int);
void g(char);
g(p); // ERROR: ambiguous
You can also request explicit conversions using the usual cast notations:
long l = static_cast<int>(p); // convert to int, then to long
g((char)p); // convert to char
How does the compiler deduce , how to call the right overload?
Whenever there's a type mismatch, the compiler looks for a conversion sequence. The rules are quite complicated, but basically the sequence can include at most one user-defined conversion (using either an operator like this, or a converting construction), as well as standard conversions such as int to long.
This is sometimes called the Return Type Resolver idiom or "overload on return type". The conversion operator to call is selected thanks to the context of use where an implicit conversion is needed (for example based on the type of an object to initialize or assign to). For example:
#include <stdio.h>
class RtR {
public:
operator int() const
{
puts("operator int()");
return 42;
}
operator double() const
{
puts("operator double()");
return 3.14;
}
};
void f(int) {}
int main()
{
RtR x;
int i = x; // or int i = RtR();
double d = x;
f(x);
}
output:
operator int()
operator double()
operator int()
See it live.
In 13.1 Overloadable declarations:
Function declarations that differ only in the return type cannot be
overloaded. [ Note: ... It does not apply to sets of functions
fabricated as a result of name lookup (e.g., because of using-directives) or overload resolution (e.g.,
for operator functions) ... ]
Hence this is valid:
struct X {
// Conversion function:
operator int () { return 1; }
operator double () { return 2; }
};
In addition (not relating directly to the question):
struct Y
{
// Operator (Function call):
int operator () (int) { return 1; }
double operator () (double) { return 2; }
// Operator (Subscripting):
int operator [] (int) { return 1; }
double operator [] (double) { return 2; }
// Operator (Shift):
int operator << (int) { return 1; }
double operator << (double) { return 2; }
// and more ...
};
The above code is for operator type conversions and provide an implicit way to cast the Proxy type to int and char.
The compiler "knows" based on the context of the conversion calls, for instance:
Proxy p;
// p_int will be set equal to p.my_owner->getInt()
int p_int = p;
// p_char will be set equal to p.my_owner->getChar()
char p_char = p;
The fact that it's a proxy is irrelevant; the same thing works for any class. Those are conversion operators, and the compiler does select the right version based on how it's used in the calling code.
struct S {
operator int() const { return 1; }
operator double() const { return 2.0; }
};
int main() {
S s;
int i = s;
double d = s;
std::cout << i << ' ' << d << '\n';
return 0;
}

Explicit conversion and templated conversion operator

I wanted to somehow extend the Microsoft type _variant_t so it accepts implicit/explicit conversions to/from additional types. To do so, I wrote the following class:
class value_type
{
public:
/* Constructors */
value_type(const std::string& str) : m_variant(str.c_str()) {}
template <typename Type> value_type(const Type& value) : m_variant(value) {}
/* Conversion operators */
operator const _variant_t&() const { return m_variant; }
operator std::string() const { return static_cast<const char*>(m_variant); }
template <typename Type> operator Type() const { return static_cast<Type>(m_variant); }
private:
_variant_t m_variant;
};
That is, if every instance of _variant_t in the code is replaced with value_type, it "works" the same.
Lets consider the following function, which returns a _variant_t:
_variant_t foo();
If I write:
std::string bar()
{
value_type v = foo();
return v;
}
It compiles just fine.
But if I change the previous code like that:
std::string bar()
{
return value_type(foo());
}
or:
std::string bar()
{
return static_cast<std::string>(value_type(foo()));
}
The compilation fails with the following message:
configuration.cpp(41) : error C2668: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string' : ambiguous call to overloaded function
If I remove the template <typename Type> operator Type... line, everything compiles.
Now I understand what the compilater says (it doesn't know which operator to use) but I don't understand why: It would seem logical to use the operator std::string when converting to std::string. What am I missing ?
Thank you.
The problem is that string's constructor is overloaded. So if returning involves invoking a string constructor, then there are multiple choices: argument could be converted to const char*, allocator<char> or string.
static_cast<string>(x) is the same as string(x).
I suppose your first faulty example should read return string(foo());, not return value_type(foo());