Skip to content
Ahmed Essam edited this page Aug 25, 2019 · 16 revisions

Lots of times, we want to make sure certain conditions in the code, such as range bounds on variables, non-negative indices, matching vector/matrix sizes, parameters in [0,1], etc. There are two different cases to check:

  1. User specified inputs. I.e. when users have the power to break these conditions
  2. Internal checks. I.e. when the user is not able to break the condition, but you want to make sure that things are working in your code

First of all, number 2. is not necessary at all. It is just for your convenience. You should rather write proper unit-tests for your code than being lazy and relying on assertions to check whether things are working correctly. But if you must, you should use the ASSERT macro, which will throw an error when assertion fails with information on file name and line number where it was used. Make sure that you're building in debug mode, by providing cmake with the flag DCMAKE_BUILD_TYPE=Debug, since these assertions are removed in release builds.

For the other one use the templated function require<ExceptionType>, and give proper error messages, which means information of what is wrong, and in particular how it differs from what was expected. If ExceptionType is not specified require throws by default ShogunException when the assertion fails. It is encouraged, however, that you use more specific exception type. Example

void foo(index_t i, SGVector<index_t> inds)
{
...
    require(i >= 0, "Provided index ({}) must be greater than 0.", i);
    require<std::invalid_arguments>(i >= 0, , "Provided index ({}) must be greater than 0.", i);
...
    require(inds.size() == this->bar.size(), "Provided index vector length ({}) must match the length of internal vector ({}).\n", inds.size(), this->bar.size());
}

Note that you should not type class or method name, but instead write clear and descriptive error messages that make sense to the user, not the developer.

Finally

  • Use proper English (Start with capital letters, write sentences)
  • Make sure that you don't cause segfaults in your assertions, check bounds, pointer valid, etc
  • Provide require with exceptions of proper types if possible.
void foo(SGVector<index_t> inds)
{
...
    // First check makes sure that second check does not segfault
    require(inds.size() >= 1, "Length of provided vector ({}) must be at least 1.", inds.size());
    require(inds[0] > 0, "First element of provided vector ({}) must be greater than 0.", inds[0]);
}
void foo(CKernel* kernel)
{
...
    // First check makes sure that second check does not segfault
    require(kernel, "No kernel provided.");
    require(kernel->get_width() >= 1, "Provided kernel width ({}) must be greater than 1.0.", kernel->get_width());
}

For more information, see SGIO class source code.

Clone this wiki locally