Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compilation time message (after preprocessor) to use with `if constexpr`

I am using an if constexpr to test the presence of a method in a class. If the method is not present, I wish to tell the user the function was ignored and he should implement it but it is not mandatory.

The idea is to give a message similar to #warning but the preprocessor is processed before the template thus this will never work.

Is there any compilation time feedback alternative that came with C++17? Or any planned for C++20?

Runnable example

template <typename State>
void callStateFunction(const State& state) {
  if constexpr (false) {
    state.method();
  } else {
    #warning The method State::method() was not implemented
  }
}
like image 541
Alexis Paques Avatar asked Jul 10 '20 16:07

Alexis Paques


People also ask

Does constexpr compile time?

constexpr functions Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument. When its arguments are constexpr values, a constexpr function produces a compile-time constant.

Is constexpr always evaluated at compile time?

constexpr functions will be evaluated at compile time when all its arguments are constant expressions and the result is used in a constant expression as well.

What does if constexpr do?

Constexpr ifIf the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

Should I use constexpr everywhere?

Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.


1 Answers

Not a great solution, I suppose, but...

If your compiler activate all warnings (-Wall for g++ and clang++, by example), you can substitute the #warning row with something that generate a warning.

By example, an unused (maybe with a talking name) variable.

I've tried with

template <typename State>
void callStateFunction(const State& state) {
  if constexpr (false) {
    state.method();
  } else {
    int method_not_implemented[sizeof(State)];
  }
}

and calling with a non-method value (callStateFunction(1), by example), I get

prog.cc: In instantiation of 'void callStateFunction(const State&) [with State = int]':
prog.cc:13:23:   required from here
prog.cc:7:9: warning: unused variable 'method_not_implemented' [-Wunused-variable]
    7 |     int method_not_implemented[sizeof(State)];
      |         ^~~~~~~~~~~~~~~~~~~~~~

from g++ (head 11.0.0) and

prog.cc:7:9: warning: unused variable 'method_not_implemented' [-Wunused-variable]
    int method_not_implemented[sizeof(State)];
        ^
prog.cc:13:4: note: in instantiation of function template specialization 'callStateFunction<int>' requested here
   callStateFunction(1);
   ^

from clang++ (head 11.0.0)

I suggest that the unused variable depends from the template typename (State) otherwise, if I define a non-dependent variable as

int method_not_implement;

I get a warning from clang++

prog.cc:7:9: warning: unused variable 'method_not_implemented' [-Wunused-variable]
    int method_not_implemented;
        ^

also without calling the function with a non-method object.

like image 119
max66 Avatar answered Sep 22 '22 16:09

max66