Deciphering a function overload not found error message - c++

I have the following code :-
class A : public B {
public:
_container (B* b) {
container_ = b;
}
private:
B* container_;
};
void foo(const A& a, const B& b) {
A new_a (a);
new_a._container(&b);
}
If I try to compile this using icpc12, I get :-
error: no instance of overloaded function "A::_container" matches the argument list
argument types are: (const B *)
object type is: A
new_a._container (&b);
Now, I understand that the first line of the error means there is some sort of type mismatch between the function being called and the function definitions available and I'm trying to narrow down the problem using the other two lines of the error message.
What do the second and third lines mean?

The function takes a non-const pointer as an argument, and you're passing a const pointer.

Related

type deduction fail: shared_ptr of derived template to base template as function argument

Here I declared two template classes: A and B, B derives from A:
template<typename T>
class A {
public:
int a;
T t;
};
template<typename T>
class B : public A<T> {
public:
int b;
};
And I make a shared_ptr<B<T>> and assign it to shared_ptr<A<T>>, it's ok:
auto b = std::make_shared<B<std::string>>();
std::shared_ptr<A<std::string>> a = b;
Here I declared a template function accept shared_ptr A<T>:
template<typename T>
void proc(std::shared_ptr<A<T>> &a) {
std::cout << a->a << std::endl;
}
it accepts a as argument, but rejects b:
proc<std::string>(a); // OK
proc<std::string>(b); // template argument deduction/substitution failed
// cannot convert 'b' (type 'std::shared_ptr<B<std::__cxx11::basic_string<char> > >') to type 'std::shared_ptr<A<std::__cxx11::basic_string<char> > >&'
I use g++ as compiler with -std=c++11.
This error brings me a lot problems and how could I fix this elegantly?
Given proc<std::string>(b);, b needs to be converted to std::shared_ptr<A<std::string>>. That means a temporary std::shared_ptr<A<std::string>> will be constructed and then passed to proc. The parameter type of proc is an lvalue-reference to non-const, i.e. std::shared_ptr<A<T>> &, which can't bind to temporaries.
You can change the parameter type to lvalue-reference to const, which could bind to temporaries. e.g.
template<typename T>
void proc(const std::shared_ptr<A<T>> &a) {
// ^^^^^
std::cout << a->a << std::endl;
}
First of all, you make a shared_ptr called:
auto b = std::make_shared<B<std::string>>();
Is of type std::shared_ptr<B<std::string>> and,
std::shared_ptr<A<std::string>> a = b;
Is of type std::shared_ptr<A<std::string>>...
In your function parameter, however, you have:
void proc(std::shared_ptr<A<T>> &a)
Which only points to the shared_ptr of A, not B, so it is obvious that B won't become A...
The solution would be to remove the lvalue reference of a from the function definition, like:
void proc(std::shared_ptr<A<T>> a)
so, it doesn't refer to A, and B can easily be converted to A during function call...
Edit: Added an explanation...
Explanation:
Remember pointers? from C... yes, they do the same function of references:
// Compilable both in C and C++...
int add(int a, int b, int * more_than_3) {
int const result = a + b;
if (result > 3)
*more_than_3 = 1;
return result;
}
Yeah, these which would the function of pseudo-return types in C. Like:
// Compilable both in C and C++...
int main(void) {
int more_3;
int const res = add(2, 3, &more_3);
printf("Sum of 2 + 3 is %i\n", res);
if (more_3)
printf("Given two numbers' sum is more than 3");
}
Here, an extra argument is passed which takes the address of a variable (References also do the same thing, they share their address with the variable with whom they are referenced...)
Remember, references and pointers store the address of another variable inside of them...
This might be the reason why they made the address of operator (&) also act for references in C++...
Also, unneeded, but the answer which was posted here by #songyuanyao worked, because:
void proc(std::shared_ptr<A<T>> const &a)
uses a constant reference, a reference to a constant expression, not a variable, so it didn't matter if they mismatched (A and B)

called object type 'void (B::*)(int)' is not a function or function pointer

I am trying to wrap my head around passing method as function argument. Here is a simplified example which returns a compilation error that I don't understand
class B
{
private:
int j;
public:
void foo(int i){std::cout << i + this->j << std::endl;}
void setj(int J){j=J;}
};
class A
{
private:
B b;
public:
void call(void (B::*fun)(int i), int i) { b.*fun(i); }
void setBj(int j){b.setj(j);}
};
int main()
{
A a;
a.setBj(40);
a.call(B::foo, 2);
}
When compiled with
g++ -std=c++11 b.cpp -o b
I get
b.cpp:22:50: error: called object type 'void (B::*)(int)' is not a function or
function pointer
void call(void (B::*fun)(int i), int i) { b.*fun(i); }
~~~^
b.cpp:31:12: error: call to non-static member function without an object
argument
a.call(B::foo, 2);
~~~^~~
2 errors generated.
I don't understand the first error message. I understand that I am calling foo as if it was a static method, which it is not but I don't understand how to pass a non-static method.
Two problems.
To invoke a pointer to a member function, you need to first apply a pointer to member access operator, that obtains a callable expression. Then you add a call. Now it just so happens that .* is of lower precedence than the function call operator. So the first fix:
(b.*fun)(i)
A a pointer to member function can only be obtained by applying unary & on the fully qualified function name. So the second fix:
a.call(&B::foo, 2);

Is there any difference between the following two?

I define a global non-member method for + overloading
Like
ClassA operator+(const ClassA& a, const ClassB& b);
{
blah blah ;
}
In the communicative one, I can use
1)
ClassA operator+(const ClassB& b, const ClassA& a)
{
return operator+(a,b);
}
2)
ClassA operator+(const ClassB& b, const ClassA& a)
{
return a + b;
}
Any difference between 1 and 2?
Beyond the obvious difference pointed out first by #barakmanos in the comments ("the second one is more readable"), there is another technical difference.
Assume for a second, the following definitions:
struct B;
struct A
{
void operator+(B const&) const { ::std::cout << "member\n"; }
friend void operator+(A const&, B const&) { ::std::cout << "friend\n"; }
};
struct B { };
Now, consider the following three statements:
operator+(A(), B());
A().operator+(B());
A() + B();
The first one obviously calls the friend (free) function, the second one calls the member. However, the third one would call either if the other was not defined. In this special case, it cannot find a better match and would thus be ill formed. There are a few ways to modify this behaviour, e.g. if the member function was different in const-requirements, the expression could be correct and just lead to a larger overload set.
This demonstrates the difference in your two expressions: operator+(a,b) only considers free functions and not member functions overloading the binary plus operator.
In fact, the C++ standard has an example for another difference:
A() + B() only does argument dependent lookup, while operator+(A(), B()) does a normal function lookup. This means that the following is an error (taken from C++11 ยง13.3.1.2.10):
struct A { };
void operator + (A, A);
struct B {
void operator + (B);
void f ();
};
A a;
void B::f() {
operator+ (a,a); // error: global operator hidden by member
a + a; // OK: calls global operator+
}

Constructor overloading chooses cast operator instead of struct type

I've encountered a weird situation where the compiler chooses to cast a structure even though there's a perfectly good constructor that receives the structure type.
A small example:
struct A
{
operator int() {return 1;}
};
struct B
{
B(A& a) { OutputDebugStringA("A constructor\n"); }
B(int i) { OutputDebugStringA("int constructor\n"); }
};
A test () { A a; return a;};
int _tmain(int argc, _TCHAR* argv[])
{
B b(test());
return 0;
}
Explanation: A has a cast operator to int. B has 2 overloaded constructors, one that accepts A reference, and one that accepts int.
Function test() returns an A object.
For some reason, the compiler decides to cast the return value to an int, and use the constructor that accepts an int. int constructor
Can anyone explain why this happens ? I have a few theories, but I would like an answer that is based on something real (maybe a quote from the standard).
Note:
I can get the expected result (constructor that accepts the type) by changing the constructor signature to: B(const A& a) or B(A&& a)
Your constructor takes a non-const reference to A, which cannot bind to a temporary. You pass it a temporary here:
B b(test());
// ^^^^^^ temporary A
so the only valid constructor is the one taking an int. You can change this behaviour by making the relevant constructor take a const reference:
B(const A& a) { OutputDebugStringA("A constructor\n"); }
//^^^^^
and similarly for B(A&& a); in C++11.
Alternatively, keeping the original constructor signature and passing an lvalue also results in the constructor call:
A a;
B b(a);

Why is this rvalue call ambiguous?

Why is this rvalue call ambiguous? I can have AA and AA& and the compiler will know to use AA&. But when i add in the third option i get an error. Obviously AA&& is a better overload then the others like int for an int is better then long. Why is this ambiguous? Is there a way i can keep all 3 overloads and make it clear which one i want? (Typecasting (AA&&) will not do it).
struct AA{
void*this_;
AA() { this_=this; }
//not valid, use AA&, AA(AA a){ this_=this; }
AA(AA&a){ this_=this; }
AA(AA&&a){ this_=a.this_; }
};
void movetest(AA s) {}
void movetest(AA& s) {}
//This gets me the ambiguous error void movetest(AA&& s) {}
AA&& movetest() { return AA(); }
void MyTestCode2(){
AA a;
AA b(a);
AA c = movetest();
movetest(AA());
}
I can have AA and AA& and the compiler
will know to use AA&
Yes, in the case of movetest(AA());, only movetest(AA) is viable, because a (lvalue) reference to non-const cannot be bound to an rvalue. However, an rvalue reference is said to bind directly to a temporary. Thus, for overload resolution purposes the functions
void movetest(AA)
void movetest(AA&&)
are equal, because the implicit conversion sequences used to convert AA() to AA and AA&&, respectively, are equal. The former is not better, because the direct reference binding is also considered an identity conversion.
Agreed with decltype. This is really no different than this C++03/98 ambiguity:
struct AA {};
void movetest(AA s) {}
void movetest(AA& s) {}
int main()
{
AA a;
movetest(a);
}
test.cpp:9:5: error: call to 'movetest' is ambiguous
movetest(a);
^~~~~~~~
test.cpp:3:6: note: candidate function
void movetest(AA s) {}
^
test.cpp:4:6: note: candidate function
void movetest(AA& s) {}
^
1 error generated.