"No matching function for call error" with g++ - c++

I have a class A
template<typename T>
class A : public std::auto_ptr<T>
{
typedef std::auto_ptr<T> Super;
public:
A() : Super() { }
A(T* t) : Super(t) { }
A(A<T>& o) : Super(o) { }
...
};
and IConstEnumerator
template<typename T>
struct IConstEnumerator
{
...
virtual IEnumerator<T>* GetEnumerator() = 0;
virtual IConstEnumerator<T>* GetEnumerator() const = 0;
};
When I run this code
AP< IConstEnumerator<IPort> > pe = node.GetPorts().GetEnumerator(); ;
I got errors from not finding correct match with g++ compiler.
error: no matching function for call to ‘AIR::A<AIR::IConstEnumerator<AIR::IPort> >::AP(AIR::A<AIR::IConstEnumerator<AIR::IPort> >)’
note: candidates are: AIR::A<T>::A(AIR::A<T>&) [with T = AIR::IConstEnumerator<AIR::IPort>]
note: AIR::A<T>::A(T*) [with T = AIR::IConstEnumerator<AIR::IPort>]
What's wrong with the class A? It works well with MSVC.
EDIT
Using copy constructor explicitly seems to solve this issue. A< IConstEnumerator<IPort> > pe(node.GetPorts().GetEnumerator())

Your A copy constructor takes its argument by non-const reference:
A(A<T>& o) : Super(o) { }
^ not const
Your example probably tries to copy a temporary object and the non-const reference can't bind to the temporary object. Visual C++ has an evil extension that allows this to work; you have to be careful to avoid relying on that extension if you want your code to be portable.
If you are trying to mimic auto_ptr's copy constructor, you need to also implement something similar to auto_ptr_ref, which is used as a helper to allow copying temporary auto_ptrs. I describe how this is accomplished in the accepted answer to How could one implement std::auto_ptr's copy constructor?
For what it's worth, deriving from std::auto_ptr is a bit odd; consider using composition instead of inheritance, if you can (there isn't a whole lot in std::auto_ptr that you'd benefit from by deriving from it anyway).

Without the exact code that actually causes the error it's hard to know for sure, but I suspect that from AIR::A<T>::A(AIR::A<T>&) what happening is you're trying to pass a temporary (possibly implicit) object into AIR::A<T>::A and MSVC lets you bind the temporary to the non-const reference parameter, while g++ quite properly prohibits this. Can you make the parameter const?

I'd guess you're lacking A(A<T> const & o).
VS (incorrectly) permits getting a non-const reference to a temporary, g++ behaves properly

It looks compiler talks that it cannot choose right function: constructor A from pointer A<T>::A(T*) or copy constructor A<T>::A(A<T> &). Maybe it worth to change definition to explicit A(T* t) : Super(t) { }

Related

Error passing shared_ptr<Derived>& as shared_ptr<Base>& without const

I got compile error when passing shared_ptr<Derived>& as shared_ptr<Base>&, see the below code and detailed question.
Note: this question is similar to "Passing shared_ptr<Derived> as shared_ptr<Base>" but not duplicate.
#include <memory>
class TBase
{
public:
virtual ~TBase() {}
};
class TDerived : public TBase
{
public:
virtual ~TDerived() {}
};
void FooRef(std::shared_ptr<TBase>& b)
{
// Do something
}
void FooConstRef(const std::shared_ptr<TBase>& b)
{
// Do something
}
void FooSharePtr(std::shared_ptr<TBase> b)
{
// Do something
}
int main()
{
std::shared_ptr<TDerived> d;
FooRef(d); // *1 Error: invalid initialization of reference of type ‘std::shared_ptr<TBase>&’ from expression of type ‘std::shared_ptr<TDerived>’
FooConstRef(d); // *2 OK, just pass by const reference
FooSharePtr(d); // *3 OK, construct a new shared_ptr<>
return 0;
}
Compiled by g++ -std=c++11 -o shared_ptr_pass_by_ref shared_ptr_pass_by_ref.cpp
Env: Ubuntu 14.04, g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Detailed question:
Why is it OK to pass by const reference (*2), but not OK to pass by reference (*1)?
Note: I know the best practice is to pass by const reference, but just want to know why the compile error occurs.
You seem to expect some kind of template covariance, whereby AnyTemplateClass<Derived> can bind to AnyTemplateClass<Base>&. Templates don't work this way. Generally, AnyTemplateClass<Derived> and AnyTemplateClass<Base> are two distinct, completely unrelated classes.
A specific template class may, or course, provide a relationship in some form. shared_ptr<T> in particular has a templated constructor accepting shared_ptr<U> for any U such that U* is convertible to T*.
FooConstRef(d) call works by constructing a temporary - effectively
shared_ptr<TBase> temp(d);
FooConstRef(temp);
But temporaries can't bind to non-const references, that's why FooRef(d) doesn't work in a similar way.

implicit conversion at call by value and polymorphism

Consider the following scenario:
Some polymorphic classes:
struct iClass
{
virtual ~iClass(){}
};
struct CommonClass : public iClass
{
char str[128];
CommonClass() { ... }
...
};
struct SpecificClass : public iClass
{
char str[32];
SpecificClass () { ... }
SpecificClass (SpecificClass& src) { strcpy(...); ... }
SpecificClass (CommonClass& src) { strcpy(...); ... }
SpecificClass (const CommonClass& src) { strcpy(...); ... }
void foo() { ... }
};
Furthermore a function:
void someFunc(SpecificClass sc) { sc.foo(); } // pass by value: i want it copied!
int main ()
{
CommonClass comCl;
someFunc(comCl); // <- Error: no matching function for call to 'SpecificClass::SpecificClass(SpecificClass)' NOTE: no &
SpecificClass specCl(comCl);
someFunc(specCl); // Works normal, but the str gets copied double times this way, isnt it?
return 0;
}
Why does the compiler not allow the conversion from CommonClass to SpecificClass in the first function call although a new SpecificClass gets constructored on the call anyways and there is a constructor for this specific conversion?
And why do i get this strange error message? A call to a copy constructor without a reference?
Can anyone share some insight into this problematic?
Btw, i have to use gcc 4.1.2
someFunc requires an argument of type SpecificClass, and you provide one of type CommonClass. Since you have defined a conversion constructor
SpecificClass::SpecificClass(CommonClass &)
this conversion can be performed implicitly, and that's great so far.
[Note, though, that your conversion constructor takes a non-const reference, which works here because you actually supply it with an lvalue – however, in general, I'd assume that taking the argument of the conversion constructor as const CommonClass & is usually better (since the conversion from one type into another isn't usually expected to alter the original).]
However, the problem occurs in the next step: The freshly converted object of type SpecificClass now needs to be copied into the function argument sc of someFunc. For this you need a copy constructor for SpecificClass which can take an rvalue (that's what the freshly converted SpecificClass object is, because it's a temporary).
Your copy constructor
SpecificClass::SpecificClass(SpecificClass &)
is declared to take a non-const lvalue reference, which can't bind to the temporary. So you must change this into
SpecificClass::SpecificClass(const SpecificClass &)
to fix the problem. And that's the usual way of declaring a copy constructor anyway.
One other thing I can't help noticing: You have a function someFunc that is meant to be called on objects of a very specific type only. Yet you call it on a general (base class?) type. Clearly, this can be made to work in the way you described, but it is in many ways counter-intuitive and not well-aligned with the principle of object-oriented programming. It also makes me wonder how the 'specific' object is actually created from the 'common' one, i.e. what the conversion constructor actually does. Intuitively, I'd assume the 'common' object given as input lacks the 'specific' information to create a 'specific' object.
In any case, you may want to reconsider the structure of your class hierarchy and/or the purpose of someFunc. None of this is directly related to the problem described in your question, though.

Error "recursive on all control paths" when copy constructor is used and virtual function present

The error below is confusing me. Here is a short piece of a much more complicated code. It appears strange to me, that only the existence of both a templated constructor and a virtual method cause an error, and only when copy-initializing an object.
Does anyone have an idea? Thanks.
class A
{
long *p;
public:
A():p(0)
{
}
template<class T>
A(T val):p(val)// 1
{
}
operator long*()
{
return p;
}
};
class B
{
virtual void f()// 2
{
}
};
class C : public A, public B
{
};
void main()
{
C c;
The next line in main() is
A a=c;
and this triggers the error below if both the lines marked // 1 and // 2 are present:
warning C4717: 'C::C' : recursive on all control paths, function will cause runtime stack overflow
But when the following is used in main(), there is no error:
A a;
a=c;
}
What you have is a nasty confluence of copy elision and a constructor that makes a copy of the parameter.
First, let's clear up a misunderstanding: A a = c; is not equivalent to A a; a = c;. The first calls the copy ctor, the second calls the assignment operator. See for yourself using this code sample.
The constructor A::A<T>(T) could make a copy of T whenever it is called. Unfortunately, if you call it using an A parameter (or in your example C, which is-a A), the parameter will attempt to copy itself, which calls A::A<T>(T) again, which copies itself again, and again... until stack overflow.
Why doesn't this happen when you don't have the virtual void f() in B? This is a side effect of copy elision, which is an implementation-dependent feature. Having the virtual method there might have been enough for visual studio to decide not to elide the copy, but in any case you shouldn't depend on it. This is why you are strongly advised not to have observable side-effects for copy ctors.
Just in case you were looking for a solution, you can remove the copy by changing A::A<T>(T) to take a reference, like A::A<T>(T&). Even better, take a const T& because this helps ensure that there are no side effects in the ctor (as you can't modify the T).
A a=c; // this results in A::A(C c) template constructor instantiation.
After that it is recursion since to make a copy, you need to make a copy, you need to make a copy.... :)
For proper usage refer this.

Is it possible to inherit from boost::function?

I'd like to know if it's possible to inherit from boost::function.
Basically, for ease of use, what I'd like to
is have a type "Delegate" which is basically a boost::function.
It's just for ease of use in some code I'm writing.
I at one point typedef'd boost::function to Delegate, but typedef'ing in my experience plays hell with gdb stuff. Especially if it's templated, so I wanted to avoid that (ever try debugging stl containers that've been typdeffed? oofta).
I found some code online which gave some sort of an example:
template<class Signature>
class Delegate : public boost::function<Signature>
{
public:
using boost::function<Signature>::operator();
};
Now, as I attempt to use it I get some errors.
A usage example would be:
Tank * tankptr = new Tank();
Delegate<void ()> tankShoot(boost::bind(boost::mem_fn(&Tank::Shoot),tankptr));
This yields errors such as
error: no matching function for call to ‘Delegate<void ()()>::Delegate(boost::_bi::bind_t<boost::_bi::unspecified, boost::_mfi::mf0<void, Tank>, boost::_bi::list1<boost::_bi::value<Tank*> > >)’
Delegate.h:26: note: candidates are: Delegate<void ()()>::Delegate()
Delegate.h:26: note: Delegate<void ()()>::Delegate(const Delegate<void()()>&)
If I had to guess why I'm getting these errors, I'd have to say it's cause I'm missing
some kind of copy constructor that takes whatever base a boost::bind constructor returns.
Any thoughts on how I can get past this hurdle, or anyone able to point me to good examples
of inheriting from boost::function?
Deriving from a class does not automatically 'inherit' the base class constructors for the derived class. You will need to create all required constructors there.
hKaiser was correct in my needing to write the required constructors.
I had a hell of a time of it, until I found the interface file for the boost class "function"
on their website.
In the end I ended up with something like:
template<class Signature>
class Delegate : public boost::function<Signature>
{
public:
///use the functor operator from the original class
using boost::function<Signature>::operator();
///base constructor for our new type,
Delegate() : boost::function<Signature>() {/*empty*/}
///copy constructor for our new type
Delegate(const boost::function<Signature>& x) : boost::function<Signature>(x) {/*empty*/}
Delegate& operator=(const Delegate & _delegate)
{
boost::function<Signature> x = _delegate;
try
{
dynamic_cast<boost::function<Signature> & >(*this) = x;
}
catch(bad_cast &bc)
{
cout << "Bad Cast Exception. " << bc.what();
int * ptr = NULL;
*ptr = 1; //force seg fault instead of assert
}
return *this;
}
};
I'm not sure if I'm properly using the dynamic_cast (in the context of adhering to good coding practices) or if I even need it there in the assignment operator, but it does work, and works extremely well.

non-copyable objects and value initialization: g++ vs msvc

I'm seeing some different behavior between g++ and msvc around value initializing non-copyable objects. Consider a class that is non-copyable:
class noncopyable_base
{
public:
noncopyable_base() {}
private:
noncopyable_base(const noncopyable_base &);
noncopyable_base &operator=(const noncopyable_base &);
};
class noncopyable : private noncopyable_base
{
public:
noncopyable() : x_(0) {}
noncopyable(int x) : x_(x) {}
private:
int x_;
};
and a template that uses value initialization so that the value will get a known value even when the type is POD:
template <class T>
void doit()
{
T t = T();
...
}
and trying to use those together:
doit<noncopyable>();
This works fine on msvc as of VC++ 9.0 but fails on every version of g++ I tested this with (including version 4.5.0) because the copy constructor is private.
Two questions:
Which behavior is standards compliant?
Any suggestion of how to work around this in gcc (and to be clear, changing that to T t; is not an acceptable solution as this breaks POD types).
P.S. I see the same problem with boost::noncopyable.
The behavior you're seeing in MSVC is an extension, though it's documented as such in a roundabout way on the following page (emphasis mine) http://msdn.microsoft.com/en-us/library/0yw5843c.aspx:
The equal-sign initialization syntax is different from the function-style syntax, even though the generated code is identical in most cases. The difference is that when the equal-sign syntax is used, the compiler has to behave as if the following sequence of events were taking place:
Creating a temporary object of the same type as the object being initialized.
Copying the temporary object to the object.
The constructor must be accessible before the compiler can perform these steps. Even though the compiler can eliminate the temporary creation and copy steps in most cases, an inaccessible copy constructor causes equal-sign initialization to fail (under /Za, /Ze (Disable Language Extensions)).
See Ben Voigt's answer for a workaround which is a simplified version of boost::value_initialized, as pointed out by litb in a comment to Ben's answer. The docs for boost::value_initalized has a great discussion of the problem, the workaround, and some of the pitfalls of various compiler issues.
I don't think template metaprogamming is needed. Try
template <class T>
void doit()
{
struct initer { T t; initer() : t() {} } inited;
T& t = inited.t;
...
}
There's §12.8/14:
A program is ill-formed if the copy constructor or the copy assignment operator for an object is implicitly used and the special member function is not accessible.
And then there's §12.8/15:
When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects.
So, the question is really, if the implementation omits the call to the copy constructor (which it is clearly allowed to do), is the copy constructor actually used?
And, the answer to that is yes, per §3.2/2:
A copy constructor is used even if the call is actually elided by the implementation.
Have you seen what happens when you compile using /Wall with MSVC? It states the following about your class:
nocopy.cc(21) : warning C4625: 'noncopyable' : copy constructor could not be
generated because a base class copy constructor is inaccessible
nocopy.cc(21) : warning C4626: 'noncopyable' : assignment operator could not be
generated because a base class assignment operator is inaccessible
GCC remedy:
create a copy constructor for noncopyable (and an assignment operator ideally!) that does what it can to copy the information from noncopyable_base, namely invoking the constructor for noncopyable_base that has no parameters (since that is the only one accessible by noncopyable) and then copying any data from noncopyable_base. Given the definition of noncopyable_base, however, it seems there is no data to copy, so the simple addition of noncopyable_base() to the initializer list of a new noncopyable(const noncopyable &) function should work.
Take note of what MSVC said about your program though. Also note that if you use T t() rather than T t = T(), another warning (C4930) is generated by MSVC, though GCC happily accepts it either way without any warning issued.