Reference to void* casting when conversion member function operator exists - c++

Came across the following example:
https://godbolt.org/g/yYgZox
#include <iostream>
struct A {
operator void* (){ return nullptr; }
};
A a;
A& getA () {
return a;
}
int main(int, char**)
{
int x = 0;
// this works
if (std::cout << x) {
return 1;
}
// this works only because we have operator void* defined
if (getA()) {
return 2;
}
return 0;
}
Why it is OK for the compiler to cast a reference to void* when such defined as a member function?

Related

How to watch instance method operator() result in VSCode C++?

My code is as follows:
class Foo{
public:
int operator()(int i)
{
return 1;
}
int operator++(int i)
{
return 1;
}
};
int main()
{
Foo foo;
int a = foo++;
int b = foo(0);
float c = 0;
}
The problem is that I am not able to watch foo(0):
foo++ is visible normally.
I think the reason is that overloaded function call operator becomes a FunctionObject type (see here https://en.cppreference.com/w/cpp/language/operators).
Is it possible to watch it?
As n-1-8e9-wheres-my-share-m commented, foo.operator()(0) works for me:

Deduced type with 'auto &&' as function return type

In the following snippet, the function B::f() is a "wrapper" around the function A::f(). But I assume that A::f() return type is an "opaque" type which I don't know if it has a value or reference semantics. So I cannot use auto or const auto & as return type for B::f(). I thought that auto && would do the trick, but it does not as auto && is deduced as A::OpaqueType &... Is it possible here to avoid writing A::OpaqueType?
#include <iostream>
struct A {
using OpaqueType=int; // But it could have been `const int &`
OpaqueType f() const {
return i;
}
int i=42;
};
struct B {
// how could I use `auto` here to avoid writing the `A::OpaqueType`?
// I would have expected that `auto &&` would do the trick but it does not
A::OpaqueType f() const {
return a.f();
}
A a;
};
int main()
{
B b;
std::cout << b.f() << std::endl;
}
The following snippet confuses me, as I would have expected that the return type of f() and g() would be int, but it is int & for f() and int && for g() (I don't even understand why it is not the same)... How this can be explained?
#include <iostream>
auto &&f() {
int i=42;
return i;
}
struct A {
int f() {return i;}
int i=42;
};
auto &&g() {
A a;
return a.f();
}
int main()
{
if (std::is_same_v<decltype(f()), int &>) {
std::cout << "f() return type is 'int &'\n";
}
if (std::is_same_v<decltype(g()), int &&>) {
std::cout << "g() return type is 'int &&'\n";
}
}
Thanks!
Pretty sure what you are looking for is decltype(auto). This will return by value if the expression in the return statement returns by value, and it will return by reference if the expression in the return statement returns by reference. That would give you
decltype(auto) f() const {
return a.f();
}

C++ primitive array accessing by class

I want to access a primitive type array using a class.
I'm using Visual C++ 2013
class CInt
{
public:
CInt() { val_ = 0; }
CInt(int x) { val_ = x; }
private:
int val_;
};
int arr[2];
CInt index;
arr[index] = 2; // ERROR!
I tried to overload size_t() operator but still doesn't work.
Is something like that possible in C++/C++11?
I suspect you have an error, not because of your class, but where you are doing the array assignment. You must do the array assignment within a function: (this should work, assuming you overloaded the conversion operator correctly)
arr[index] = 2; // ERROR! <-- you can't do this outside a function
int main() {
arr[index] = 2; // <-- must be within a function
How did you do the overloading of the size_t() operator? The following works for me:
#include <iostream>
class CInt
{
public:
CInt() { val_ = 0; }
CInt(int x) { val_ = x; }
operator size_t() const { return val_; }
private:
int val_;
};
int main() {
int arr[2];
CInt index;
arr[index] = 2;
// output: 2
std::cout << arr[index] << std::endl;
}

When is ADL applied?

There are 3 examples:
I.
typedef int foo;
namespace B
{
struct S
{
operator int(){ return 24; }
};
int foo(B::S s){ return 0; }
}
int main()
{
int t=foo(B::S()); //24, ADL does not apply
}
II.
namespace B
{
struct S
{
operator int(){ return 24; }
};
int foo(B::S s){ return 0; }
}
int main()
{
int t=foo(B::S()); //0, ADL applies
}
III.
namespace B
{
struct S
{
operator int(){ return 24; }
};
int foo(B::S s){ return 0; }
}
int foo(B::S s){ return 12; }
int main()
{
int t=foo(B::S()); //error: call of overloaded ‘foo(B::S)’ is ambiguous
//ADL applies
}
It is not clear for me what is the actual conditions to ADL lookup will be apply? I need in reference to standard described it.
This Standard paragraph clarifies, and even has an example very much like your first example.
3.4.1/3:
The lookup for an unqualified name used as the postfix-expression of a function call is described in 3.4.2 [basic.lookup.argdep]. [Note: For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply. The rules in 3.4.2 have no effect on the syntactic interpretation of an expression. For example,
typedef int f;
namespace N {
struct A {
friend void f(A &);
operator int();
void g(A a) {
int i = f(a); // f is the typedef, not the friend
// function: equivalent to int(a)
}
};
}
Because the expression is not a function call, the argument-dependent name lookup (3.4.2) does not apply and the friend function f is not found. -end note]
Your first example does not illustrate ADL. In the line
int t=foo(B::S());
foo is typedefed to int.
The following code has some better illustrations of ADL.
#include <iostream>
namespace B
{
struct S
{
operator int(){ return 24; }
};
int foo(S s){ return 100; }
int bar(S s){ return 400; }
}
namespace C
{
struct S
{
operator int(){ return 24; }
};
int foo(S s){ return 200; }
}
int bar(C::S s){ return 800; }
int main()
{
// ADL makes it possible for foo to be resolved to B::foo
std::cout << foo(B::S()) << std::endl;
// ADL makes it possible for foo to be resolved to C::foo
std::cout << foo(C::S()) << std::endl;
// ADL makes it possible for bar to be resolved to B::bar
std::cout << bar(B::S()) << std::endl;
// ADL makes it possible for bar to be resolved to ::bar
std::cout << bar(C::S()) << std::endl;
}

What is ->* operator in C++?

C++ continues to surprise me.
Today i found out about the ->* operator. It is overloadable but i have no idea how to invoke it. I manage to overload it in my class but i have no clue how to call it.
struct B { int a; };
struct A
{
typedef int (A::*a_func)(void);
B *p;
int a,b,c;
A() { a=0; }
A(int bb) { b=b; c=b; }
int operator + (int a) { return 2; }
int operator ->* (a_func a) { return 99; }
int operator ->* (int a) { return 94; }
int operator * (int a) { return 2; }
B* operator -> () { return p; }
int ff() { return 4; }
};
void main()
{
A a;
A*p = &a;
a + 2;
}
edit:
Thanks to the answer. To call the overloaded function i write
void main()
{
A a;
A*p = &a;
a + 2;
a->a;
A::a_func f = &A::ff;
(&a->*f)();
(a->*f); //this
}
Just like .*, ->* is used with pointers to members. There's an entire section on C++ FAQ LITE dedicated to pointers-to-members.
#include <iostream>
struct foo {
void bar(void) { std::cout << "foo::bar" << std::endl; }
void baz(void) { std::cout << "foo::baz" << std::endl; }
};
int main(void) {
foo *obj = new foo;
void (foo::*ptr)(void);
ptr = &foo::bar;
(obj->*ptr)();
ptr = &foo::baz;
(obj->*ptr)();
return 0;
}
The overloaded ->* operator is a binary operator (while .* is not overloadable). It is interpreted as an ordinary binary operator, so in you original case in order to call that operator you have to do something like
A a;
B* p = a->*2; // calls A::operator->*(int)
What you read in the Piotr's answer applies to the built-in operators, not to your overloaded one. What you call in your added example is also the built-in operator, not your overloaded one. In order to call the overloaded operator you have to do what I do in my example above.
Like any other opperator, you can also call it explicitly:
a.operator->*(2);