CODING_STYLE.md
GOLDEN RULE: Follow the style of the existing code when you make changes.
-> or ..: but one after it, except in the ternary operator: one on both sides.Yes:
if (a == b[i])
printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'.
foo->bar(
someLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName
);
cout <<
"some very long string that contains completely irrelevant " <<
"text that talks about this and that and contains the words " <<
"\"lorem\" and \"ipsum\"" <<
endl;
No:
if( a==b[ i ] ) { printf ("Hello\n"); }
foo->bar(someLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName,
anotherLongVariableName);
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;
To set indentation and tab width settings uniformly, the repository contains an EditorConfig .editorconfig file, which describes some of the styles used and which is recognized by many IDE's and editors.
using namespace declarations in header files.using namespace solidity; and other project local namespaces is fine in cpp files, and generally encouraged.using namespace at file level for third party libraries, such as boost, ranges, etc.Only in the header:
#include <cassert>
namespace myNamespace
{
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
}
#ifdef/#define/#endif file guards. Prefer #pragma once as first line below file comment.\.GOLDEN RULE: Preprocessor: ALL_CAPS; C++: camelCase.
All other entities' first alpha is lower case.
Use solAssert and solUnimplementedAssert generously to check assumptions that span across different parts of the code base, for example before dereferencing a pointer.
nullptr is a valid argument, use references otherwise. Often, std::optional is better suited than a raw pointer.auto if the type is very long and rather irrelevant.Yes:
enum class Accuracy
{
Approximate,
Exact
};
struct MeanSigma
{
float mean = 0.0f;
float standardDeviation = 1.0f;
};
double const d = 0;
int i = 0;
int j = 0;
char* s = nullptr;
MeanAndSigma ms meanAndSigma(std::vector<float> const& _v, Accuracy _a);
Derived* x = dynamic_cast<Derived*>(base);
for (auto i = x->begin(); i != x->end(); ++i) {}
No:
const double d = 0;
int i, j;
char *s;
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
Derived* x(dynamic_cast<Derived*>(base));
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
m_.m_.foo
m_foofoo() [ also: for booleans, isFoo() ]setFoo()IMyInterface, CMyImplementation)using to typedef. e.g. using ints = std::vector<int>; rather than typedef std::vector<int> ints;shared_ptr<X> rather than shortening to ptr<X>.using Guard = std::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it is clear in meaning and used commonly.libsolidity -> libevmasm -> libsolutil -> boost -> STL)..h file should be the first include in the respective .cpp file.Example:
#include <libsolidity/codegen/ExpressionCompiler.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/codegen/CompilerContext.h>
#include <libsolidity/codegen/CompilerUtils.h>
#include <libsolidity/codegen/LValue.h>
#include <libevmasm/GasMeter.h>
#include <libsolutil/Common.h>
#include <libsolutil/SHA3.h>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <utility>
#include <numeric>
See this issue for the reason: this makes it easier to find missing includes in header files.
Herb Sutter and Bjarne Stroustrup:
Herb Sutter and Andrei Alexandrescu:
Scott Meyers: