Clang outputs error "no matching construct for initialization" - c++

Compiling this code snippet with clang-425.0.27 ( based on LLVM3.2svn) :
class CStorage
{};
typedef boost::shared_ptr< CStorage > AccessorPtr;
class CTest
{
public:
CTest( const CStorage &rAccessor )
: m_Accessor( rAccessor ){}
private:
AccessorPtr m_Accessor;
};
Getting compilation error:
**error**: no matching constructor for initialization of 'AccessorPtr' (aka 'shared_ptr<CStorage>')
: m_Accessor( rAccessor ){}
**note**: candidate constructor (the implicit copy constructor) not viable: no known conversion from
'const FNPNS::TSM::CDirectBlockAccessor' to 'const boost::shared_ptr<FNPNS::TSM::CDirectBlockAccessor>' for 1st argument
template<class T> class shared_ptr

The boost::shared_ptr constructor wants a pointer, you're passing it a reference. You might want to change your own constructor to take a pointer as well, or create a new CStorage object on the heap using the reference.

As #Joachim suggested your ctor expects a pointer.
It might be better to pass a shared pointer (or a weak pointer, depending on your use case) which will keep the pointer in memory.

Related

Compile error when using std::variant with gmock 1.8 object

Let's have this code using gmock 1.8:
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <variant>
class Obj {
public:
MOCK_METHOD0( mock, void() );//<-!!!
};
using Variant = std::variant<Obj>;
TEST(Test, Test) {
Obj obj;
Variant variant = obj;
}
When trying to compile this with clang++ there is this compile error:
error: no viable conversion from 'Obj' to 'Variant' (aka 'variant<Obj>')
Variant variant = obj;
^ ~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/variant:1081:7: note: candidate constructor not viable: no known conversion from 'Obj' to 'const std::variant<Obj> &' for 1st argument
variant(const variant& __rhs) = default;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/variant:1093:2: note: candidate template ignored: substitution failure [with _Tp = Obj &, $1 = void, $2 = void]: implicit instantiation of undefined template 'std::variant<Obj>::__to_type_impl<18446744073709551615, false>'
variant(_Tp&& __t)
^
(g++'s error only says
error: conversion from ‘Obj’ to non-scalar type ‘Variant’ {aka ‘std::variant<Obj>’} requested
Variant variant = obj;
^~~
)
When the line with MOCK_METHOD0 macro is commented out, the code compiles all right. I'm convinced it's the copy constructor (the one from line 1081) that gets invoked in that case.
Why is that? Will the problem disappear if I move to gmock 1.10? Or is it impossible to use variants of gmock mocks? Thanks for any explanation or a hint on how to find it myself.
If you expand the MOCK_METHOD0 macro, you will see that it inserts the following data member to your class definition:
class Obj
{
public:
// ...
mutable ::testing::FunctionMocker<void()> gmock0_mock_12;
};
Since you do not provide your own copy-constructor, one will be implicitly generated by the compiler. Its default implementation will try to perform a member-wise copy. However, checking the definition of FunctionMocker, one can see the following notice:
// There is no generally useful and implementable semantics of
// copying a mock object, so copying a mock is usually a user error.
// Thus we disallow copying function mockers. If the user really
// wants to copy a mock object, they should implement their own copy
// operation, for example:
//
// class MockFoo : public Foo {
// public:
// // Defines a copy constructor explicitly.
// MockFoo(const MockFoo& src) {}
// ...
// };
FunctionMocker(const FunctionMocker&) = delete;
FunctionMocker& operator=(const FunctionMocker&) = delete;
That is, FunctionMocker objects are non-copyable, and so are mock objects (their implicitly generated copy-constructors are also deleted).
That's reasonable. Should a copy of a mock have the same expectations? Should it double-check the expectations on destruction?
If you want to put the mock in a variant, you can build it in-place, either:
std::variant<Obj> variant(std::in_place_type_t<Obj>{});
or:
std::variant<Obj> variant;
variant.emplace<Obj>();

How to use std::make_shared<T> to a std::vector<std::shared_ptr<T>> without push_back? [duplicate]

(Using Visual Studio 2010) I'm trying to create a shared_ptr of an existing class in my project (class was written a decade before std::shared_ptr existed). This class takes a non-const pointer to another object, it's empty parameter constructor is private.
class Foobar {
public:
Foobar(Baz* rBaz);
private:
Foobar();
}
When I try to create a shared_ptr to it, things don't go well:
Baz* myBaz = new Baz();
std::shared_ptr<Foobar> sharedFoo = std::make_shared<Foobar>(new Foobar(myBaz));
On VS2010, this gives me
error C2664: 'Foobar::Foobar(const Foobar &)' : cannot convert parameter 1 from 'Foobar *' to 'const Foobar &'
3> Reason: cannot convert from 'Foobar *' to 'const Foobar'
For some reason it appears to be calling the copy constructor of Foobar instead of the constructor that takes a Baz*.
I'm also not sure about the cannot convert from 'Foobar *' to 'const Foobar' part. My best interpretation is that my templated-type of shared_ptr<Foobar> is wrong. I made it shared_ptr<Foobar*> but this seems wrong, all examples I've seen don't make the type a raw pointer.
It seems that making everything shared_ptr<Foobar*> compiles properly, but will that prevent the Foobar object from getting deleted properly when all shared_ptr's go out of scope?
Edit: This seems related, but I'm not using Boost: boost make_shared takes in a const reference. Any way to get around this?
Edit2: For clarity, if you're wondering why I'm using make_shared(), in my actual code the sharedFoo variable is a class member of a third class (independent of Foobar and Baz).
That should be;
std::shared_ptr<Foobar> sharedFoo = std::make_shared<Foobar>(myBaz);
...since make_shared constructs the actual object for you by running the constructor.

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.

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

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

Does Hinnant's unique_ptr implementation incorrectly fail to convert derived-to-base in this case?

I'm currently trying to use Howard Hinnant's unique_ptr implementation, and am running into a compile error. Here is some sample code:
struct Base {};
struct Derived : public Base {};
void testfun(boost::unique_ptr<Base>);
void test()
{
unique_ptr<Derived> testDerived;
unique_ptr<Base> testBase(move(testDerived)); // ok, construct base explicitly from derived
testfun(move(testBase)); // ok, pass base to testfun which expects base
testfun(unique_ptr<Base>(move(testDerived))); // ok, explicitly converts to unique_ptr<Base>
testfun(move(testDerived)); // error on this line
}
The error I get is
In function 'void test()':
error: no matching function for call to 'boost::unique_ptr<Base, boost::default_delete<Base> >::unique_ptr(boost::unique_ptr<Base, boost::default_delete<Base> >)'
note: candidates are: boost::unique_ptr<T, D>::unique_ptr(boost::detail_unique_ptr::rv<boost::unique_ptr<T, D> >) [with T = Base, D = boost::default_delete<Base>]
note: boost::unique_ptr<T, D>::unique_ptr(boost::unique_ptr<T, D>&) [with T = Base, D = boost::default_delete<Base>]
error: initializing argument 1 of 'void testfun(boost::unique_ptr<Base, boost::default_delete<Base> >)' from result of 'boost::unique_ptr<T, D>::unique_ptr(boost::unique_ptr<U, E>, typename boost::enable_if_c<((((! boost::is_array<U>::value) && boost::detail_unique_ptr::is_convertible<typename boost::unique_ptr<U, boost::default_delete<U> >::pointer,typename boost::detail_unique_ptr::pointer_type<T, D>::type>::value) && boost::detail_unique_ptr::is_convertible<E,D>::value) && ((! boost::is_reference<D>::value) || boost::is_same<D,E>::value)), void>::type*) [with U = Derived, E = boost::default_delete<Derived>, T = Base, D = boost::default_delete<Base>]'
It seems like the offending line should not fail. Is this a bug in the implementation, a limitation of the implementation due to the lack of C++0x language features, or a misunderstanding of the rules of unique_ptrs?
(Note, I know this won't work at run-time because I'm moving the same thing more than once; I'm just trying to figure out the compile-time error.)
For a similar example, see this which should fail too
unique_ptr<Base> testBase = move(testDerived);
The problem here is how the move semantic is implemented: The "copy constructor" takes a non-const reference, thus not being able to bind to temporaries. To still "move" from temporaries, the class has a conversion function (following are really just conceptual - they may be differently implemented in detail):
operator rv<T>() { return rv<T>(*this); }
And a constructor will take that object:
unique_ptr(rv<T> r):ptr_(r.release()) { }
Here is an example that fails for the same reason:
// move helper. rv<> in unique_ptr
struct E { };
// simulates a unique_ptr<D>
struct D { };
// simulates the unique_ptr<B>
struct A {
A() { }
// accepts "derived" classes. Note that for unique_ptr, this will need that
// the argument needs to be copied (we have a by-value parameter). Thus we
// automatically ensure only rvalue derived-class pointers are accepted.
A(D) { }
// these will accept rvalues
A(E) { }
operator E() { return E(); }
private:
A(A&); // private, error if passed lvalue
};
Now, consider this code:
// allowed: goes: D -> A(D)
A a((D()));
// compile failure. Goes:
// D -> A(D) -> A(E)
A a = D();
Copy initialization will first convert to A. But then, the temporary A object is tried to be copied again to the final object. This will need the way using operator E. But that's another user defined conversion in the initialization, which the standard forbids:
13.3.3.1/4
When invoked for the copying of the temporary in the second step of a class copy-initialization, [...], only standard conversion sequences and ellipsis conversion sequences are allowed.
This is why your code fails.
Further research has lead me to this note, leading me to believe that this is a known limitation of the implementation:
3 of the tests currently fail for me (fail at compile time,
supposed to compile, run and pass). These are all associated with the
converting constructor specified in [unique.ptr.single.ctor]. When
the source and target are of different type, this emulation demands
that the conversion be explicit, and refuses to compile on implicit
conversions:
unique_ptr<base> b(unique_ptr<derived>()); // ok
unique_ptr<base> b = unique_ptr<derived>(); // causes 3 compile time failures under unique.ptr/unique.ptr.single/unique.ptr.single.ctor .