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?
Related
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.
I'm trying to do have Derived derive from Base:
class Base
{
public:
Base() {};
};
template <class T>
class Derived : public Base
{
public:
Derived::Derived()
{
}
};
This gives me the following error:
error C3254: 'Derived':
class contains explicit override '{ctor}' but does not derive from an
interface that contains the function declaration
note: see reference to
class template instantiation 'Derived' being compiled
error C3244:
'Derived::Derived(void)': this method was introduced by 'Unknown>'
not by 'Base'
I'm totally new to templates, what simple steps am I missing? This seems like a pretty basic thing.
You need to omit the "Derived::" prefix. You would only use it to refer to a symbol that was inherited, or injected into the namespace of the class Derived. So the only prefix that makes sense is "Base::" here. It has nothing to do with templates.
class Base
{
public:
Base() {};
};
template <class T>
class Derived : public Base
{
public:
Derived() {}
};
See a working Live Demo.
I'm having trouble understanding why my template hierarchy won't pass constructor arguments deeper than one layer.
So far I've read that it may have something to do with namespacing or template constructors being unnamed. My various attempts at getting the constructor arguments through to the base class with scoping directives have failed.
// test.cc
#include <string>
// Base class, obviously.
template <typename T>
class Base {
public:
Base(const T& t) : _t(t) {}
virtual ~Base() { }
virtual T getVal() const { return _t; }
private:
T _t;
};
// First derivation. This works, although it is explicit.
class DerivedOne : public virtual Base<std::string>
{
public:
DerivedOne(const std::string& path) : Base<std::string>(path) {}
virtual ~DerivedOne() {}
};
// Second derivation. Constructor fails to compile unless I explicitly
// pass the 'path' argument to Base in the initializer list or create a
// default constructor for Base (which, of course, leaves Base::_t
// uninitialized).
class DerivedTwo : public virtual DerivedOne
{
public:
DerivedTwo(const std::string& path) : DerivedOne(path) {}
// This works
// DerivedTwo(const std::string& path) : DerivedOne(path), Base(path) {}
virtual ~DerivedTwo() {}
};
int main()
{
return 0;
}
The compiler complains:
test.cc: In constructor ‘DerivedTwo::DerivedTwo(const string&)’:
test.cc:31:58: error: no matching function for call to ‘Base<std::__cxx11::basic_string<char> >::Base()’
DerivedTwo(const std::string& path) : DerivedOne(path) {}
^
test.cc:7:5: note: candidate: Base<T>::Base(const T&) [with T = std::__cxx11::basic_string<char>]
Base(const T& t) : _t(t) {}
^
test.cc:7:5: note: candidate expects 1 argument, 0 provided
test.cc:5:7: note: candidate: Base<std::__cxx11::basic_string<char> >::Base(const Base<std::__cxx11::basic_string<char> >&)
class Base {
^
test.cc:5:7: note: candidate expects 1 argument, 0 provided
Why do I need to declare a default constructor when it seems that the parameterized constructor should be called? Why must I explicitly pass DerivedTwo's parameter to Base, since I've passed it to DerivedOne (who should pass it to Base)?
Is there some way to avoid this duplication? Does this mean I can't use initializer lists when a base template constructor parameter is allocated on the heap in a derived class initializer list?
What is going on
When you inherit virtually, you are asking that the type you inherit from is a "singleton" within the object heiarchy (not a program-wide singleton, but a instance-wide singleton, strange as that may seem).
As a side effect, the actual most derived class is responsible for constructing the virtual base class, regardless of what intermediate classes exist.
Virtual inheritance is intended when you need to inherit from some class more than once, yet ensure that only one instance exists. Rather than work out some complex set of rules to determine whose constructor call would be the one to be called, the designers of C++ mandated that the most-derived class (the actual one being created) dictates exactly what constructor is called.
Everyone else can chime in, but only if an actual instance of that specific class (and not a more-derived one) is created does their opinion matter.
You probably don't want virtual there
virtual inheritance has almost nothing to do with virtual methods/member functions. Don't use it unless you need to for binary layout or diamond inheritance reasons.
Simply eliminate it from your code, and if you never inherit from a class along 2 different paths to the same most-derived class, you won't miss it.
class DerivedOne : public Base<std::string>
and
class DerivedTwo : public DerivedOne
and your code compiles and does what you seem to want.
When you use virtual inheritance it is always the MOST DERIVED class that initializes the virtual base. Even though your intermediate class passes a value up, it won't do that in further derived classes, which must directly initialize Base.
Since your most derived class (DerivedTwo) doesn't directly initialize Base, then Base is initialized without any parameters passed to it, and so requires a default constructor.
class DerivedTwo : public virtual DerivedOne
{
public:
DerivedTwo(const std::string& path) : Base(path), DerivedOne(path) {}
}
Alternately, stop using virtual inheritance, and just use "normal" inheritance. That is, change this:
class DerivedOne : public virtual Base<std::string>
to this:
class DerivedOne : public Base<std::string>
Unless, of course, you really need virtual inheritance. :)
I've created a header for optionally-lazy parameters (also visible in a GitHub repository).
In my original version of the code, I provided a protected default constructor for my base-class template:
template <typename VAL_TYPE>
class LazyType_Base
{
// ....
LazyType_Base(void) =default;
// ....
Then, in one of the derived classes:
template <typename VAL_TYPE>
class LazyType_Eager : public LazyType_Base<VAL_TYPE>
{
public:
LazyType_Eager(
VAL_TYPE&& final_val)
: LazyType_Base<VAL_TYPE>{}
, val_{final_val}
{}
// .....
This compiles just fine with Clang++, but in G++ 5.1, I get this error:
In file included from Test_OptionallyLazy.cpp:3:0:
OptionallyLazy.hpp: In instantiation of ‘LazyType_Eager<VAL_TYPE>::LazyType_Eager(VAL_TYPE&&) [with VAL_TYPE = int]’:
Test_OptionallyLazy.cpp:22:14: required from here
OptionallyLazy.hpp:23:5: error: ‘LazyType_Base<VAL_TYPE>::LazyType_Base() [with VAL_TYPE = int]’ is protected
LazyType_Base(void) =default;
^
OptionallyLazy.hpp:58:23: error: within this context
, val_{final_val}
What's going on here? The weirdest bit is that the other derived class does something similar that doesn't trigger an error.
Replacing the =default constructor with the explicit default implementation {} resolves the compiler error.
EDIT: Thanks to T.C., here is a real MCVE:
class Meow
{
protected:
Meow(void) =default;
public:
virtual void f() {}
};
class Purr : public Meow
{
public:
Purr()
: Meow{}
{}
};
UPDATE: it seems it's my fault, I didn't installed correctly CTP. MS weren't able to reproduce the bug.
I'd like to move a variable from a derived class to my base class (there are multiple classes between them)
Usually, I would pass the argument by const&, but I'm trying to pass it by value and move it down the hierarchy, avoiding a copy.
Here are my classes:
#include <string>
class base {
public:
explicit base(std::string url) : url_{std::move(url)} {}
// prevent copy
base(const base&) = delete;
base& operator=(const base&) = delete;
virtual ~base() {}
protected:
std::string url_;
};
class derived : public base {
public:
using base::base;
};
class derived_final : public derived {
public:
using derived::derived;
explicit derived_final(std::string url) :
derived{std::move(url)}
{
// do some stuff
}
};
int main() {
derived_final df { "test" };
}
and the log:
e:\project\test\main.cpp(25) : error C2664: 'derived::derived(const derived &)': cannot convert argument 1 from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' to 'const derived &'
Reason: cannot convert from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' to 'const derived'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
I also tried adding a move constructor to base, aswell as an op=.
But derived_final tries to use derived's copy constructor with std::string as parameter, when I try to move url to derived in derived_final's constructor.
Any ideas why this is happening?
I'm using msvc 2013 with CTP (for "using" support).
source here: https://bitbucket.org/syl/c-11-inherited-constructor-and-move/src
Seems to be a MSVC bug. GCC reports no errors.