Given the following code:
#include <boost/noncopyable.hpp>
enum Error { ERR_OK=0 };
struct Filter : private boost::noncopyable
{
Filter() {}
virtual ~Filter() {}
virtual int filter(int* data) const = 0;
};
struct SpecialFilter : public Filter, private boost::noncopyable
{
inline SpecialFilter(unsigned int min, unsigned int max) : min(min), max(max) {}
virtual ~SpecialFilter() {}
virtual int filter(int* data) const
{
// ...
return ERR_OK;
}
unsigned int min;
unsigned int max;
};
struct AClass
{
AClass() {}
AClass(const AClass& other) {}
~AClass() {}
int specialFilter(int channel, int minThreshold, int maxThreshold)
{
// ...
return filter(channel, SpecialFilter(123, 321));
}
int filter(int channel, const Filter& filter)
{
// ...
return ERR_OK;
}
};
My compiler (GCC 4.2) complains:
- warning: direct base ‘boost::noncopyable_::noncopyable’ inaccessible in ‘SpecialFilter’ due to ambiguity
- noncopyable.hpp: In copy constructor ‘Filter::Filter(const Filter&)’:
- noncopyable.hpp:27: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private
- synthezised method first required here: [return filter(channel, SpecialFilter(123, 321));]
But I don't call the copy constructor!
You never call copy constructor. The copy constructor is always called for you implicitly by the compiler. So you need to learn to recognize situations when it might be called.
When you attach a const reference to a temporary object
...
return filter(channel, SpecialFilter(123, 321));
...
the compiler has the right to perform a copy of the temporary object and require an accessible copy constructor (even if it won't be actually called). This is what is causing the problem in your case.
In other words, when you make some type non-copyable, you also give up the possibility to attach const references to temporary objects of that type.
Firstly, remove the private derivation from SpecialFilter - it is not necessary, as Filter is already not copyable. Problems like this are why I think solutions like boost::non_copyable are a bad idea - there are simpler ways of saying you don't want copies.
Secondly, though I'm not sure this is your problem, C++ says that a public copy constructor must be available to the compiler under several circimstances, even if the compiler does not actually use it.
Remember when you pass object and return object by value --> copy constructor is invoked.
Related
Consider the following code:
class BaseTask {
// Implementation here
};
class BaseSubtask {
BaseTask *_pTask;
public:
explicit BaseSubtask(BaseTask *pTask) : _pTask(pTask) { }
virtual void Run() = 0;
// The rest of implementation here.
};
template<typename taFunc> class LambdaSubtask {
taFunc _f;
public:
explicit LambdaSubtask(BaseTask *pTask, taFunc&& f)
: BaseSubtask(pTask), _f(std::forward<taFunc>(f))
{ }
LambdaSubtask(const LambdaSubtask&) = delete;
LambdaSubtask& operator=(const LambdaSubtask&) = delete;
LambdaSubtask(LambdaSubtask&&) = delete;
LambdaSubtask& operator=(LambdaSubtask&&) = delete;
virtual void Run() override final { _f(); }
// The rest of implementation here
};
Because I cannot declare a LambdaSubtask object without specifying its template type argument, and I cannot specify its template type argument because it's a lambda, I try to implement a factory method:
template<typename taFunc> inline LambdaSubtask<taFunc>
MakeLambdaSubtask(BaseTask *pTask, taFunc&& f) {
return { pTask, std::forward<taFunc>(f) };
}
Unfortunately this gives a compilation error:
copy-list-initialization of LambdaSubtask<lambda_...> cannot use an explicit constructor
With a proper factory method I could get a LambdaSubtask object as follows:
BaseTask task; // Initialization of the task is skipped in the example
auto&& lst = MakeLambdaSubtask(&task, [/* Capture here*/]() {
// Implementation here
});
So basically I want a local variable object of LambdaSubtask type, with template type being a lambda. I want to avoid extra copying of anything. Surely I want to avoid std::function as my benchmarks show it's extremely slow.
Do you know how to implement a proper factory method or get local variable object of LambdaSubtask type in another way?
My compiler is MSVC++2017 with toolset v141 , so C++11/14/17 is partially supported.
You did it unto yourself by declaring your lambda constructor explicit. Remove explicit and your code should compile.
Remember, uniform list initialization doesn't work with explicit constructors.
Fundamentally, you're trying to do this:
struct X {
explicit X(int ) { }
};
X foo() { return {4}; }
That doesn't work because the X constructor is explicit and you're doing copy-list-initialization. The workaround is just to explicitly construct:
X foo() { return X{4}; }
// ^^^
Note that in C++17, this does not incur a copy or move. Prior to C++14, this wouldn't incur a copy or move either but the move would still have to be well-formed.
The other alternative would be to remove the explicit mark from your constructor, which is what is preventing you from returning a braced-init-list.
As a side-note, be careful about:
template<typename taFunc>
LambdaSubtask<taFunc> MakeLambdaSubtask(BaseTask *pTask, taFunc&& f) { ... }
If you're passed in an lvalue function, you're going to keep a reference to it - so that's an extra lifetime you have to worry about. For this reason, it's common to instead return LambdaSubtask<std::decay_t<taFunc>>. This ensures that the Subtask has a valid function for its lifetime.
Consider the following code where I'm trying to introduce a default constructor as well as a parameterized one for class A. This way was introduced in recent c++ improvements.
class A {
private:
unsigned int count;
public:
A(int new_c) : count(new_c) {}
A() : A(10) {}
};
vs the old way of setting a default parameter on parameterized constructor and ignoring the default constructor completely.
class A {
private:
unsigned int count;
public:
A(int new_c = 5) : count(new_c) {}
};
Is there any advantage using 1st method over the 2nd one apart from following modern conventions?
Functionally there is no difference. Know that there is even another option available with non-static member initialization (since C++11):
class A {
private:
unsigned int count = 10;
public:
A() = default;
A(int new_c) : count(new_c) {}
};
There is no advantage in case like in your example (I'd even choose the 2nd option as more clear in such example)
Delegating constructors where added to ease work when default values were not enough.
For example
struct Point3d
{
Point3d(int x, int y, int z);
Point3d(Point2d p) : Point3d(p.x, p.y, 0) {}
}
Advantage will be more visible in case of larger class where can be a few constructors . In new way you will be able to write one constructor and then set it to others. This is less error prone.
class A {
private:
unsigned int count;
int other;
float otherfloat;
public:
A( unsigned int count, int other, float otherfloat ) : count( count), other( other ), otherfloat( otherfloat ) {}
A(int new_c) : A(new_c, 0, 0.0 ) {}
A() : A(10) {}
};
While technically there is no difference, the idea behind the creation of forwarding constructors was a different one.
Imagine the following class:
class sample {
complexType member;
bool createdWithInt;
public:
sample() : member(5), createdWithInt(false) {
/* code ... */
}
sample(int param) : sample() {
createdWithInt = true;
/* other code */
}
};
So this class is hard to implement with default parameters:
Its behaviour does not depend on the value of the parameter, it rather depends on the presence.
One might to try to implement it with a helper function void creator() that executes the code ... bit from the constructor without arguments. However this would mean duplicating the initialization list (or discarding the RAII principle if one initializes from within creator()).
Note: createdWithInt could be initialized from the initialization list, if another constructor was added, that takes a bool and both current constructors forward to that one. For the sake of the example this has been omitted.
I have this class that has many class members, and a lot of different constructors.
Until now, I used a constructor initialization list in each of the constructors that I have, tuning each member the way I wanted.
This is quite tedious, because everytime I add a new member to my class, I have to visit each constructor and update the initialization list to add a default value to this member.
So, I thought I would add a method to initialize the values I need. Problem! Since the method is executed after the initialization list, the particular values I put in this init list are overriden by my method.
Quick exemple:
class A
{
public:
A();
A( B b );
A( int i );
// A( .... ); plenty of them
private:
int member1, m2, m3,m4;
bool b1,b2, b3;
// ....
// every time I add a member I have to modify the initialization lists
// solution: agregate member initialization in a member function:
void init_members();
}
// init list constructors
A::A() : m1(false), m2(false), m3(false), m4(true) .... // looong list
{
}
A::A( B b) : m1(b.state()), m2(false), m3(false), ... // loong list
{
}
// problem, if I use init_members:
void A::init_members()
{
m1 = false;
m2 = false;
m3 = false;
// ...
}
A::A( int i ) : m1( true)
{
init_members(); // overrides m1 !!!
}
So, my question: can I mix list initializer and method initializers, so that list initializers have precedence over the method initializer?
In my example above, I want m1 to stay true for the last constructor.
Note: I know I could move the initialization list after the method call, but this means I'd assign twice the values to the members : once in init_members(), then overriding it in the constructor. Not optimal enough :-)
I was hoping for some little trick, if you have that in stock.
In C++11 one option could be constructor delegation, where one constructor simply calls one of the other constructors, so as to avoid duplicating code.
This is what it looks like:
class A {
public:
A(int,int,double);
A(int,int);
A(double);
A();
private:
...
};
A::A(int a,int b,double c) {
// the real work to initialize the class
}
// A(int,int) delegates to A(int,int,double), passing along a
// default value for the double
A::A(int a,int b) : A(a,b,0.0) {}
A::A(double c) : A(1,2,c) {} // A(double) delegates to A(int,int,double)
A::A() : A(1.0) {} // A() delegates to A(double)
Make sure you don't create any loops. Also typically you'll want a single constructor to do most of the real work while the others just marshal the values they want to pass to that constructor. We'll call this the 'designated constructor'. The designated constructor should be the one that takes the most parameters and doesn't use any default values. Eventually all the constructors should call the designated constructor, directly or indirectly.
Note the pattern: constructors that use some default values pass those defaults along to constructors that use fewer defaults, until you arrive at the function with no defaults at all. This is the opposite of what you're trying to do with your init_members() method. You have a function that sets all the defaults, and then you try to override some of them. If you can't use C++11 features, you would be better off emulating the designated constructor pattern: init_members() will be your designated initializer and it will not have any defaults. You can use an initializer method for each constructor which takes the arguments it's given, and throws in a few default values to call another init_members overload.
However one issue with the designated initializer/constructor is that the defaults are scattered all over the place. Another option in C++11 besides delegation is 'in-class initialization', which allows all the default values to be gathered together.
class A {
public:
A(int,int,double);
A(int,int);
A(double);
A();
private:
int a = 1,b = 2; // in-class initialization gathers all the defaults together
double c = 1.0;
};
Given the above, all constructors will automatically initialize the member values to those defaults unless you explicitly initialize it to something else in that constructor.
A::A(int a,int b,double c) : a(a), b(b), c(c) {}
A::A(int a,int b) : a(a), b(b) {} // member c is automatically initialized to 1.0
A::A(double c) : c(c) {} // members a and be are automatically initialized to 1 and 2
A::A() {}; // all members are initialized with their in-class values.
Here's an example of using init_members():
class A {
public:
A(int a,int b,double c) { init_members(a,b,c); }
A(int a,int b) { init_members(a,b); }
A(double c) {init_members(c);}
A() { init_members(); }
private:
void init_members(int,int,double) { ... }
void init_members(int a,int b) { init_members(a,b,1.0); }
void init_members(double c) { init_members(1,2,c); }
void init_members() { init_members(1.0); }
...
};
This method value initializes members before init_members() can be called, so members are initialized twice. I'm not sure there's a way to fix that in C++03.
For cases like this, I do not use the Base/Member Initializer List (the members have "garbage" or "default-constructor" values at that point in the constructor), and I use the init_() function (called from the constructor-body). Then, the constructors call the init_() function, and there is a single maintenance point.
Similarly, my clear() function would also call the init_() function, for a single maintenance point of "default" values.
For your case, it would be:
A::A(void)
//...no Base/Member-Initializer list...
{
init_members();
}
A::clear(void)
{
init_members();
}
...and the override:
A::A(int override_m1)
{
init_members();
m1 = override_m1;
}
Hm, I don't want to know what names your colleagues give you if they spot a class like this... Imagine what happens if they have to repair or extend a monster of this kind. I newly assigned a task to switch some of the many As we have in our code base (and which became unmaintainable) to something like this:
class AKeyValueStorage {
// would be some kind of shared storage if meant to be
// copyable and don't forget moving if your're on c++11!
std::map<std::string, boost::any> mMembers;
public:
template<class Key, class T>
T const & Get(Key const & pKey) const
{
auto tTmp = mMembers.find(ToString(pKey));
if (tTmp != mMembers.end()) {
return boost::any_cast<T const &>(*tTmp);
}
// throw if none, or return default
}
template<class Key, class T>
void Set(Key const & pKey, T const & pValue) const
{
mMembers[ToString(pKey)] = pValue; // replace if found, insert if none
}
};
I was going through a tutorial for building an AST with the help of Clang/LLVM.
I see this syntax there:
struct PPContext {
// Takes ownership of client.
PPContext(clang::DiagnosticClient* client = 0,
const std::string& triple = LLVM_HOSTTRIPLE)
: diagClient(client == 0?new clang::TextDiagnosticPrinter:client),
diags(diagClient),
target(clang::TargetInfo::CreateTargetInfo(triple)),
headers(fm),
pp(diags, opts, *target, sm, headers)
{
// Configure warnings to be similar to what command-line `clang` outputs
// (see tut03).
// XXX: move warning initialization to libDriver
using namespace clang;
diags.setDiagnosticMapping(diag::kind,diag::MAP_IGNORE);
//diag::warn_pp_undef_identifier was the initial value instead of diag::kind. But I changed since it gave error.
}
~PPContext()
{
delete diagClient;
delete target;
}
clang::DiagnosticClient* diagClient;
clang::Diagnostic diags;
clang::LangOptions opts;
clang::TargetInfo* target;
clang::SourceManager sm;
clang::FileManager fm;
clang::HeaderSearch headers;
clang::Preprocessor pp;
};
And:
//What is the constructor doing here ? The construct looks very different and difficult to comprehend !!!
// Could someone break it up for me ?
PPContext(clang::DiagnosticClient* client = 0,
const std::string& triple = LLVM_HOSTTRIPLE)
: diagClient(client == 0?new clang::TextDiagnosticPrinter:client),
diags(diagClient),
target(clang::TargetInfo::CreateTargetInfo(triple)),
headers(fm),
pp(diags, opts, *target, sm, headers)
{
// Configure warnings to be similar to what command-line `clang` outputs
// (see tut03).
// XXX: move warning initialization to libDriver
using namespace clang;
diags.setDiagnosticMapping(diag::kind,diag::MAP_IGNORE);
//diag::warn_pp_undef_identifier was the initial value instead of diag::kind. But I changed since it gave error.
}
Please let me know if there is any other material which would be of good help and learning experience. Thanks
These are constructor initializers. They initialized class members with the value given to them. For instance:
class TestClass
{
private:
int someField;
public:
TestClass() : someField(5) { }
};
Will initialize the member someField to have a value of 5 during the call to the TestClass() constructor. You can separate multiple initializers with a , to initialize multiple members. You can also pass parameters from the constructor to these initializers such as:
class TestClass
{
private:
int someField;
public:
TestClass(int _someField) : someField(_someField) { }
};
When this constructor is called, the value passed to _someField will be used to initialize someField.
Also consider inheritance. Using the second TestClass as our base we get the following derived type:
class TestClassDerived : public TestClass
{
public:
TestClassDerived(int _someField) : TestClass(_someField) { }
};
That's how you can construct a base class from a derived type and pass parameters to a non-default constructor. Without this you wouldn't be able to construct the base with the appropriate parameters using a non-default constructor.
It's called a constructor initialization list, which is used for inheritance and initializating member variables.
Click this link for a good explanation of this topic.
One scenario this is required is dealing with inheritance. Consider the following:
class Base
{
public:
Base(int n)
{
}
};
class Derived : Base
{
public:
// Error! How do we construct Base? We never pass n
// to the constructor of Base.
Derived(int n)
{
}
};
How can we change the above to compile? With a constructor initialization list:
class Base
{
public:
Base(int n)
{
}
};
class Derived : Base
{
public:
// Now your compiler is happy.
Derived(int n) : Base(n)
{
}
};
This constructur is in the format
PPContext(arg1, arg2)
: initConstructor1,
...,
initConstructor5
where you can exchange initConstructor to the initialization constructors of
the PPContext members
In the unit test of a class, I try to declare a class variable by calling explicitly the empty constructor and pass it to a function that excepts a reference to the interface of the type I'm declaring, but the compiler produces error. When I just declare it without any explicit constructor call the function accepts it.
See the code below:
//classundertest.h
class IController;
class CClassUnderTest
{
public:
CClassUnderTest() {}
virtual ~CClassUnderTest() {}
unsigned int Run(IController & controller);
};
//testclassundertest.h
#include "UnitTest++.h"
#include "classundertest.h"
#include "icontroller.h"
class CTestController : public IController
{
public:
CTestController() : IController() {}
virtual ~CTestController() {}
virtual void Play(unsigned int i) {}
};
struct CClassUnderTestFixture
{
CClassUnderTest classUnderTest;
};
TEST_FIXTURE(CClassUnderTestFixture, RunTest)
{
CTestController controllerA;
CHECK_EQUAL(classUnderTest.Run(controllerA), 105U);
CTestController controllerB();
CHECK_EQUAL(classUnderTest.Run(controllerB), 105U);
}
The compiler believes controllerB is the reference of the constructor:
error: no matching function for call to `CClassUnderTest::Run(CTestController (&)())'
error: candidates are: unsigned int CClassUnderTest::Run(IController&)
I'm confused by why the compiler won't allow me to call the constructor when instantiating controllerB, especially when the production code seems okay with this?
This line:
CTestController controllerB();
is the declaration of a function that takes nothing and returns a CTestController. For default construction, you must simply leave off the parenthesis.
This is related to something called the "most vexing parse". Consider:
struct S {};
int main()
{
S s(S()); // copy construct a default-constructed S ...?
}
This doesn't work. This declares s as a function that takes a pointer to a function that takes nothing and returns an S, that returns an S. To fix this, you can use an extra set of parenthesis:
struct S {};
int main()
{
S s((S())); // copy construct a default-constructed S :)
}