C++ - Overriding Virtual Templated Member Functions - c++

In this example:
class MyClass
{
public:
MyClass(int i);
};
template<typename T>
class Base
{
public:
virtual std::unique_ptr<T> createObj()
{
return std::make_unique<T>();
}
};
class Derived : public Base<MyClass>
{
public:
std::unique_ptr<MyClass> createObj() override
{
return std::make_unique<MyClass>(4);
}
};
int main()
{
Derived instance;
auto createdObj = instance.createObj();
}
I cannot call the derived createObj() function. It seems the code is trying to still call the base version with the MyClass instance which leads to compilation failures since the required construction arguments are not passed. Why does this not work as a normal overriden function and call the derived version that does supply the correct arguments?

You misinterpreted the error. The error message is:
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-10.3.0/lib/gcc/x86_64-linux-gnu/10.3.0/../../../../include/c++/10.3.0/memory:83:
/opt/compiler-explorer/gcc-10.3.0/lib/gcc/x86_64-linux-gnu/10.3.0/../../../../include/c++/10.3.0/bits/unique_ptr.h:962:34: error: no matching constructor for initialization of 'MyClass'
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^
<source>:15:21: note: in instantiation of function template specialization 'std::make_unique<MyClass>' requested here
return std::make_unique<T>();
^
<source>:19:7: note: in instantiation of member function 'Base<MyClass>::createObj' requested here
class Derived : public Base<MyClass>
^
<source>:6:5: note: candidate constructor not viable: requires single argument 'i', but no arguments were provided
MyClass(int i);
^
<source>:3:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
class MyClass
^
<source>:3:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
1 error generated.
Base<MyClass> tries to default construct a MyClass but MyClass has no default constuctor. Even if you are not trying to call Base<MyClass>::createObj the method must be valid because it is instantiated as part of Base<MyClass>.
In other words, merely instantiating Base<MyClass> will fail. Not calling the method does not make it less of an error.
I am not entirely sure whats the aim, but if you make the method pure virtual in Base your code compiles without issues:
#include <memory>
class MyClass
{
public:
MyClass(int i) {}
};
template<typename T>
class Base
{
public:
virtual std::unique_ptr<T> createObj() = 0;
};
class Derived : public Base<MyClass>
{
public:
std::unique_ptr<MyClass> createObj() override
{
return std::make_unique<MyClass>(4);
}
};
int main()
{
Derived instance;
auto createdObj = instance.createObj();
}
Alternatively you could provide a default contructor for MyClass.

Related

Inheritance, Copy Constructors and Implicit Typecasting

I have a derived class which I want to be able to construct using the copy constructor where the argument is an instance of the base class.
I am sure this should be possible in C++. Here is an example:
#include <string>
class Base
{
public:
friend
void swap(Base& l, Base& r)
{
using std::swap;
swap(l.a, r.a);
}
Base()
: a{1}
{
}
Base(const int a)
: a{a}
{
}
virtual
~Base()
{
}
Base(const Base& base)
: a{base.a}
{
}
Base(Base&& base)
: Base()
{
swap(*this, base);
}
Base& operator=(Base base)
{
swap(*this, base);
return *this;
}
protected:
int a;
};
class Derived : public Base
{
protected:
std::string b;
};
int main()
{
Base base(2);
Derived derived(base);
}
The error (g++ main.cpp) is:
main.cpp: In function ‘int main()’:
main.cpp:71:31: error: no matching function for call to ‘Derived::Derived(Base&)’
class Derived derived(base);
^
main.cpp:57:7: note: candidate: Derived::Derived()
class Derived : public Base
^~~~~~~
main.cpp:57:7: note: candidate expects 0 arguments, 1 provided
main.cpp:57:7: note: candidate: Derived::Derived(const Derived&)
main.cpp:57:7: note: no known conversion for argument 1 from ‘Base’ to ‘const Derived&’
main.cpp:57:7: note: candidate: Derived::Derived(Derived&&)
main.cpp:57:7: note: no known conversion for argument 1 from ‘Base’ to ‘Derived&&’
So the compiler doesn't know how to convert from an instance of Base to Derived implicitly.
I thought that this should be legal in C++. Do I require an explicit conversion statement?
What are you doing doesn't make much sense by itself because Base is not a sub-type of Derived so it can't be used as its replacement/substitution, however you could attempt to give it sense (same as with initialization from any other type) by writing a converting constructor:
class Derived : public Base
{
public:
Derived(const Base &bs) : Base(bs), b("constructed from base") {}
protected:
std::string b;
};
This would first initialize Derived Base part from bs and then init the string b with some value (though you can leave it out if you want it to be default-inited to empty string).
https://godbolt.org/z/GMELW_
Yes, you need to cast explicitely from Base to Derived. Every Mercedes is a car, but not every car is a Mercedes.
this statement Derived derived(base); or to simplify B b(A()); do an implicit conversion of type A to type B, which is legal only if class B inherit directly or indirectly from Class A.
Why ? Because class B could contains new information, in your case a string b, and a cast don't "append" information.
There is a simple way of solving this problem: By pulling the Base constructor into the scope of Derived.
This can be done with the using statement:
class Derived : public Base
{
public:
using Base::Base; // Pulls in the Base class constructors into the scope of Derived
...
};
I found what I was looking for (I couldn't remember the name so couldn't google it before). However this technique actually doesn't work due to the fact that I am using inheritance. (Or at least I don't know how to make it work.)
Type conversion operator:
Base::operator Derived()
{
Derived derived;
derived.a = a;
return derived;
}
This doesn't actually compile because the compiler doesn't know what Derived is. (Since Derived inherits from Base.) I don't know if it is possible to make this work by separating the compilation units.

Initializing base class const member in most derived class

In the below code, I initialize const member of Base class in the most derived class Grandchild.
class Base {
public:
Base(int x_) : x(x_) {}
private:
const int x;
};
class Child : public virtual Base {
public:
virtual ~Child() = 0;
};
class Grandchild : public virtual Child {
public:
Grandchild() : Base(42) {}
};
Child::~Child() {}
int main() {
Grandchild gc;
}
In case of virtual inheritance, the Base class constructor is called by the most derived class. Hence, I expect the code to compile successfully.
clang 4.0 compiles it successfully, whereas gcc 4.9.2 emits the following error:
In constructor 'Grandchild::Grandchild()':
16:27: error: use of deleted function 'Child::Child()'
9:7: note: 'Child::Child()' is implicitly deleted because the default definition would be ill-formed:
9:7: error: no matching function for call to 'Base::Base()'
9:7: note: candidates are: 3:5: note: Base::Base(int)
3:5: note: candidate expects 1 argument, 0 provided
1:7: note: constexpr Base::Base(const Base&)
1:7: note: candidate expects 1 argument, 0 provided
1:7: note: constexpr Base::Base(Base&&)
1:7: note: candidate expects 1 argument, 0 provided
What does the standard say about this?
It seems there was a change in the C++ standard clarifying the requirements of generated constructors for virtual base classes. See CWG257. As far as I understand this text your situation should be allowed. Prior to the change the situation was unclear.
This change was voted into the Working Paper in October 2009, i.e., it should be applicable to compiling with C++11.

gmock with base class constructor

I'm getting a compiler error, which I don't understand why. Or rather, I believe I'm doing what it telling me to. (Or not doing what I shouldn't do)
// InterfaceClass.h
class InterfaceClass {
public:
explicit InterfaceClass(DependencyClass * const p_dc);
};
// MockClass.h
class MockClass : public InterfaceClass {
public:
explicit MockClass(DependencyClass * const p_dc) : InterfaceClass(p_dc) {}
};
// test_MyTest.cpp
class MyTestFixture : public testing::Test {
protected:
MockDependencyClass mock_dependency;
NiceMock<mocks::MockClass> mock;
public:
MyTestFixture() : mock(&mock_depedency) {}
};
The error I'm getting when compiling my test is this:
In file included from test/test_MyTest.cpp:2:
In file included from vendor/googlemock/include/gmock/gmock.h:62:
vendor/googlemock/include/gmock/gmock-generated-nice-strict.h:92:12: error: constructor for 'testing::NiceMock<MockClass>' must explicitly initialize the base class 'InterfaceClass' which does not have a default constructor
explicit NiceMock(const A1& a1) : MockClass(a1) {
^
test/test_MyTest.cpp:43:30: note: in instantiation of function template specialization 'testing::NiceMock<MockClass>::NiceMock<DependencyClass *>' requested here
MyTestFixture(void) : mock(&mock_dependency) {
^
src/InterfaceClass:21:7: note: 'InterfaceClass' declared here
class InterfaceClass {
^
So, if I'm understanding this correctly, its telling me that my mock cannot initialise the interface class, because there is no default constructor and I haven't specified a non-default constructor to use. But I have? And if I understand gmock's source correctly, it supports constructors with up to 10 parameters.
And in my test fixture; if I make the mock a regular mock (i.e. not a NiceMock), it compiles.
What am I doing wrong here?

Compilation issues with smart pointer-based CRTP idiom

I'm trying to compile a minimal working example for the CRTP example given in this blog post, which is based on smart pointers.
Based on the code example, I've written two files, a header and source.
Header (crtp.h):
#include <memory>
class Cloneable
{
public:
virtual ~Cloneable() {}
std::shared_ptr<Cloneable> clone() const
{
return std::shared_ptr<Cloneable>(this->clone_raw());
}
private:
virtual Cloneable* clone_raw() const = 0;
};
template <typename Derived, typename Base>
class CloneInherit<Derived, Base>: public Base
{
public:
std::shared_ptr<Derived> clone() const
{
return std::shared_ptr<Derived>(static_cast<Derived*>(this->clone_raw()));
}
private:
virtual CloneInherit* clone_raw() const override
{
return new Derived(*this);
}
};
class Concrete: public CloneInherit<Concrete, Cloneable> {};
Source (example.cc):
#include <memory>
#include "crtp.h"
int main()
{
std::shared_ptr<Concrete> c = std::make_shared<Concrete>();
std::shared_ptr<Concrete> cc = c->clone();
Cloneable* p = c.get();
std::shared_ptr<Cloneable> pp = p->clone();
return 0;
}
Compilation of this code fails with the following error:
In file included from example.cc:3:
./crtp.h:18:7: error: explicit specialization of non-template class 'CloneInherit'
class CloneInherit<Derived, Base>: public Base
^ ~~~~~~~~~~~~~~~
./crtp.h:29:16: error: no matching constructor for initialization of 'Concrete'
return new Derived(*this);
^ ~~~~~
./crtp.h:33:7: note: in instantiation of member function 'CloneInherit<Concrete, Cloneable>::clone_raw' requested here
class Concrete: public CloneInherit<Concrete, Cloneable>
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:4411:26: note: in instantiation of member function 'std::__1::__shared_ptr_emplace<Concrete, std::__1::allocator<Concrete> >::__shared_ptr_emplace' requested
here
::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:4775:29: note: in instantiation of function template specialization 'std::__1::shared_ptr<Concrete>::make_shared<>' requested here
return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...);
^
example.cc:7:42: note: in instantiation of function template specialization 'std::__1::make_shared<Concrete>' requested here
std::shared_ptr<Concrete> c = std::make_shared<Concrete>();
^
./crtp.h:33:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'const CloneInherit<Concrete, Cloneable>' to 'const Concrete' for 1st argument
class Concrete: public CloneInherit<Concrete, Cloneable>
^
./crtp.h:33:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'const CloneInherit<Concrete, Cloneable>' to 'Concrete' for 1st argument
class Concrete: public CloneInherit<Concrete, Cloneable>
^
./crtp.h:33:7: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
2 errors generated.
There are ways I can fix these errors. I can delete the <Derived, Base> specialization from the declaration for CloneInherit to make the first error go away and change the definition of clone_raw() function of CloneInherit to
virtual CloneInherit* clone_raw() const override
{
return new CloneInherit(*this);
}
but I'm not sure if this will get the same results as what the post originally intended.
There are indeed several typo in his post:
Fixed version:
#include <memory>
class cloneable
{
public:
virtual ~cloneable() {}
std::unique_ptr<cloneable> clone() const
{
return std::unique_ptr<cloneable>(this->clone_impl());
}
private:
virtual cloneable * clone_impl() const = 0;
};
template <typename Derived, typename Base>
class clone_inherit : public Base
{
public:
std::unique_ptr<Derived> clone() const
{
return std::unique_ptr<Derived>(static_cast<Derived*>(this->clone_impl()));
}
private:
clone_inherit* clone_impl() const override
{
return new Derived(*static_cast<const Derived*>(this));
}
};
class concrete : public clone_inherit<concrete, cloneable>
{
};
int main()
{
std::unique_ptr<concrete> c = std::make_unique<concrete>();
std::unique_ptr<concrete> cc = c->clone();
cloneable * p = c.get();
std::unique_ptr<cloneable> pp = p->clone();
}
Demo

no matching function for call to ..constructor

I am trying to compile a code that involves inheritance.
#include "MapEntityClass.h"
class RectangularEntityClass:public MapEntityClass
{
public:
void drawOnMap(MapClass *mapObj) const;
protected:
};
The parent class is MapEntityClass, which does not have a default constructor, but has a value constructor. When I compile, I get the following error:
RectangularEntityClass.h: In constructor ‘RectangularEntityClass::RectangularEntityClass()’:
RectangularEntityClass.h:12:7: error: no matching function for call to ‘MapEntityClass::MapEntityClass()’
class RectangularEntityClass:public MapEntityClass
^
RectangularEntityClass.h:12:7: note: candidates are:
In file included from main.cpp:1:0:
MapEntityClass.h:32:5: note: MapEntityClass::MapEntityClass(const PixelLocationClass&, const ColorClass&)
MapEntityClass(
^
MapEntityClass.h:32:5: note: candidate expects 2 arguments, 0 provided
Any idea what is wrong?
In inheritance, the subclass need not have a constructor only if parent class doesn't have a constructor or only default constructor.
In any case, if parent class happens to have a parameterized constructor, the subclass should have a parameterized constructor which should invoke the parent class constructor.
Example:
class A {
int aVal;
public:
A(int);
};
A::A(int aVal)
{
this->aVal = aVal;
}
class B : public A {
int bVal;
public:
B(int, int)
};
B::B(int aVal, int bVal) : A(aVal)
{
this->bVal = bVal;
}