Refactoring with C++ 11
c++, c++11, refactoring
Solution
I would add delegating constructors and in-class member initializers to the list.
Simplification By Using Delegating Constructors and In-Class Initialization
With C++03:
class A
{
public:
// The default constructor as well as the copy constructor need to
// initialize some of the members almost the same and call init() to
// finish construction.
A(double data) : id_(0), name_(), data_(data) {init();}
A(A const& copy) : id_(0), name_(), data_(copy.data_) {init();}
void init()
{
id_ = getNextID();
name_ = getDefaultName();
}
int id_;
string name_;
double data_;
};
With C++11:
class A
{
public:
// With delegating constructor, the copy constructor can
// reuse this constructor and avoid repetitive code.
// In-line initialization takes care of initializing the members.
A(double data) : data_(data) {}
A(A const& copy) : A(copy.data_) {}
int id_ = getNextID();
string name_ = getDefaultName();
double data_;
};
Problem
Given the new toolset provided by c++ lots of programmers, aiming at code simplification, expressiveness, efficiency, skim through their old code and make tweaks (some pointless, some successful) to achieve their goals. Whilst trying not to loose too much time on such labors and just make non intrusive and self contained changes, what are the best practices? Let me cross out the obvious : Use auto to run iterator based loops : ``` for (std::vector<foo>::const_iterator it(lala.begin()), ite(lala.end()); it != ite; ++it); // becomes for (auto it(lala.cbegin()), ite(lala.cend()); it != ite; ++it); ``` Use tie for multiple assignments that just produce C-style rows of code ( how to assign multiple values into a struct at once? ) ``` a = 1; b = 2; c = 3; d = 4; e = 5; // becomes std::tie(a, b, c, d, e) = std::make_tuple(1, 2, 3, 4, 5); ``` To make a class non inheritable just declare it as "final" and delete the code that achieved such a behavior http://www.parashift.com/c++-faq/final-classes.html Use the delete keyword to explicitly hide constructors/destructors instead of declaring them private (eg code to create heap based objects, non copyable objects etc) Turn trivial functors created just to facillitate the execution of a single STL algorithm into lambda functions (apart from reducing code cluttering you'll have guaranteed inlined calls) Simplify RAII wrapping of an object by just using a smart pointer Get rid of bind1st, bind2nd and just use bind Replace hand written code for type traits (Is_ptr_but_dont_call_for_const_ptrs<> and such :) ) with standard code provided by < type_traits > Stop including boost headers for functionallity now implented in STL (BOOST_STATIC_ASSERT vs static_assert) Provide move semantics to classes (although this wouldn't qualify as a dirty/quick/easy change) Use nullptr where possible instead of the NULL macro and get rid of the code that filled containers of pointers with 0's casted to object type ``` std::vector<foo*> f(23); for (std::size_t i(0); i < 23; ++i) { f[i] = static_cast<foo*>(0); } // becomes std::vector<foo*> f(23, nullptr); ``` Clear the vector data accessing syntax ``` std::vector<int> vec; &vec[0]; // access data as a C-style array vec.data(); // new way of saying the above ``` Replace throw() with noexcept (apart from avoiding the deprecated exception specifiation you get some speed benefits http://channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler @ 00.29.42) ``` void some_func() noexcept; // more optimization options void some_func() throw(); // fewer optimization options void some_func() ; // fewer optimization options ``` Replace code where you'd push a tempory in a container and hoped that the optimizer would ellide the copy away, with an "emplace" function where available, in order to perfectly forward the argument and construct directly an object into a container without temporary at all. ``` vecOfPoints.push_back(Point(x,y,z)); // so '03 vecOfPoints.emplace_back(x, y, z); // no copy or move operations performed ``` UPDATE The answer by Shafik Yaghmour was rightfully awarded the bounty for having the greatest acceptance by the audience. The answer by R Sahu was my accepted one, because the combination of features it proposes captures the spirit of refactoring : making code clearer and cleaner and simpler and elegant.
Related problems
- Which C++ idioms are deprecated in C++11?
- My attempt at value initialization is interpreted as a function declaration, and why doesn't A a(()); solve it?
- how to assign multiple values into a struct at once?
- Why does C++11 have `make_shared` but not `make_unique`
- Why are std::shuffle methods being deprecated in C++14?
- Has the new C++11 member initialization feature at declaration made initialization lists obsolete?
- C++11 aggregate initialization for classes with non-static member initializers
- C++ range for loops with custom step