CODING-GUIDELINES.md
The TensorRT C++ Coding Guidelines are derived from several sources, primarily:
namespace foo
{
...
} // namespace foo
const or constexpr variables over #defines whenever possible, as the latter are not visible to the compiler.const.0 (only used in comparison for checking signness/existence/emptiness) and nullptr, true, false, all other literals should only be used for variable initialization.
Example:if (nbInputs == 2U)
Should be changed to:
constexpr size_t kNbInputsWBias = 2U;
if (nbInputs == kNbInputsWBias)
for or while loop in a new line.switch, while, do .. while or for statement shall be a compound statement. (use brace-delimited statements)If and else should always be followed by brace-delimited statements, even if empty or a single statement.Filenames
thisIsASubDir and thisIsAFilename.cppTypes
FooBarClassLocal variables, methods and namespaces
localFooBarNon-magic-number global variables that are non-static and not defined in anonymous namespace
gDontUseGlobalFoosNon-magic-number global variables that are static or defined in an anonymous namespace
sMutableStaticGlobalLocally visible static variable
static std::once_flag sCaskInitOnce;Public, private and protected class member variables
mNbFooValues.Constants
const int kDIGIT_NUM = 10;
NOTE: Function-scope constants that are not magic numbers or literals are named like non-constant variables:
const bool pass = a && b;
#define.FOO_VERSIONNotes:
mNbTensorDescriptorsfoo conflicts with a public member name foo, add a trailing underscore to the parameter name: foo_.1234L instead of 1234l.// clang-format off
// .. Unformatted code ..
// clang-format on
unique_ptr for single resource ownership and shared_ptr for shared resource ownership. Use weak_ptr only in exceptional cases.// This is a single line commentdoSomeOperation(/* checkForErrors = */ false);
//!.//!<.//! This is a Doxygen comment
//! in C++ style
struct Foo
{
int x; //!< This is a Doxygen comment for members
}
#if / #endif to disable code, preferably with a mnemonic condition like this:#if DEBUG_CONVOLUTION_INSTRUMENTATION
// ...code to be disabled...
#endif
// Alternative: use a macro which evaluates to a noop in release code.
#if DEBUG_CONVOLUTION_INSTRUMENTATION
# define DEBUG_CONV_CODE(x) x
#else
# define DEBUG_CONV_CODE(x)
#endif
// Not allowed in safety-critical code.
const bool gDisabledFeature = false;
void foo()
{
if (gDisabledFeature)
{
doSomething();
}
}
void* should be implicit (except if removing const).const or volatile qualification from the type of a pointer or reference.void* to a T* should be done with static_cast, not reinterpret_cast, since the latter is more forceful.reinterpret_cast as a last resort, where const_cast and static_cast won't work.dynamic_cast.// Not compliant
x = y = z;
// Not compliant
if (x = y)
{
// ...
}
const auto var = (condition0 ? a : (condition1 ? b : c));
should be changed to:
const auto d = (condition1 ? b : c);
const auto var = (condition0 ? a : d);
switch statement controlled by an enum should have a case for each enum value and not have a default clause so that we get a compile-time error if a new enum value is added.// Not compliant
switch (x) case 4: if (y) case 5: return 0; else default: return 1;
switch (x)
{
case 0: // Fall-through allowed from case 0: to case 1: since case 0 is empty.
case 1:
a();
b();
break;
case 2:
case 4:
{ // With optional braces
c();
d();
break;
}
case 5:
c();
throw 42; // Terminating with throw is okay
default:
throw 42;
}
switch (x)
{
case 0:
case 1:
{
y();
z();
break;
}
...other cases...
}
inline, absent a quantifiable benefit. Remember that functions defined in class declarations are implicitly inline.static keyword to mark a function as having internal linkage, prefer to use anonymous namespaces instead.#define and #undef of macros should be done only at global namespace.#ifdef and #ifndef directives (except in the case of header include guards). Prefer to use #if defined(...) or #if !defined(...) instead. The latter syntax is more consistent with C syntax, and allows you to use more complicated preprocessor conditionals, e.g.:#if defined(FOO) || defined(BAR)
void foo();
#endif // defined(FOO) || defined(BAR)
#if defined(FOO)
# if FOO == 0
# define BAR 0
# elif FOO == 1
# define BAR 5
# else
# error "invalid FOO value"
# endif
#endif
#pragma once as include guard.TRT_ followed by the filename, all in caps. For a header file named FooBarHello.h, name the symbol as TRT_FOO_BAR_HELLO_H.TRT_FOO_BAR_HELLO_H_#ifndef TRT_FOO_BAR_HELLO_H
#define TRT_FOO_BAR_HELLO_H
// ...
#endif // TRT_FOO_BAR_HELLO_H
using instead of typedef.std::vector::size(), such as:for (size_t i = 0; i < mTensors.size(); ++i) // preferred style
for (int i = 0; i < static_cast<int>(mTensors.size()); ++i)
int, unsigned, and bool. size_t should be used only for sizes of memory buffers.std::string) which may be compiled differently with different compilers and libraries.<cstddef> and <cstdint>.<cstdint> instead of <stdint.h>std::fill_n() instead of memset(). This is especially important when dealing with non-POD types. In the example below, using memset() will corrupt the vtable of Foo:struct Foo {
virtual int getX() { return x; }
int x;
};
...
// Bad: use memset() to initialize Foo
{
Foo foo;
memset(&foo, 0, sizeof(foo)); // Destroys hiddien virtual-function-table pointer!
}
// Good: use brace initialization to initialize Foo
{
Foo foo = {};
}
const data, the pointer itself may be const, in some usecases.char const * const errStr = getErrorStr(status);
gpuAllocator, where GPU is converted to gpu before constructing the camel case name.runtime, can be abbreviated into fully capitalized letters, e.g. RT in NvInferRT.h.__device__, __managed__ and __constant__.__device__.__global__.NOTE:
typedef __global__ void(*KernelFunc)(void* /*arg*/);.__global__ void(*KernelFunc)(void* /*arg*/) = getKernelFunc(parameters); .cuLaunch and cudaLaunch, is not CUDA code./*
* Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/