Vai al contenuto

Pretty print per funzioni in C++

Pubblicato:

Metodo semplice ma portatile per ottenere il nome della funzione corrente in C++. Ispirato a questa risposta su StackOverflow.

#include <string_view>
#include <cstddef>

#ifdef _MSC_VER
consteval std::string_view function_signature(const char *s) {
  const std::string_view prompt{s};
  // Se la funzione e 'internal', sostituisce l'intera stringa con "-"
  return prompt.find("internal::") != std::string_view::npos ? std::string_view{"-"} : prompt;
}
// MSVC++ non supporta __PRETTY_FUNCTION__, ma __FUNCTION__ è simile
#define MY_FUNCTION_SIGNATURE function_signature(__FUNCTION__)
#else
consteval std::string_view function_signature(const char *s) {
  const std::string_view prettyFunction{s};
  const std::size_t bracket = prettyFunction.rfind('(');
  const std::size_t space = prettyFunction.rfind(' ', bracket) + 1;
  const std::string_view prompt{prettyFunction.substr(space, bracket - space)};
  // Se la funzione e 'internal', sostituisce l'intera stringa con "-"
  return prompt.find("internal::") != std::string_view::npos ? std::string_view{"-"} : prompt;
}
#define MY_FUNCTION_SIGNATURE function_signature(__PRETTY_FUNCTION__)
#endif

Esempio di utilizzo:

// test.cpp
#include <cstddef>
#include <iostream>
#include <string_view>

#ifdef _MSC_VER
consteval std::string_view function_signature(const char *s) {
  const std::string_view prompt{s};
  return prompt.find("internal::") != std::string_view::npos ? std::string_view{"-"} : prompt;
}
#define MY_FUNCTION_SIGNATURE function_signature(__FUNCTION__)
#else
consteval std::string_view function_signature(const char *s) {
  const std::string_view prettyFunction{s};
  const std::size_t bracket = prettyFunction.rfind('(');
  const std::size_t space = prettyFunction.rfind(' ', bracket) + 1;
  const std::string_view prompt{prettyFunction.substr(space, bracket - space)};
  return prompt.find("internal::") != std::string_view::npos ? std::string_view{"-"} : prompt;
}
#define MY_FUNCTION_SIGNATURE function_signature(__PRETTY_FUNCTION__)
#endif

namespace myn {
class MyClass {
 public:
  void fest() { std::cout << MY_FUNCTION_SIGNATURE << std::endl; }
};
}  // namespace myn

namespace fun {

int sum(int a, int b) {
  std::cout << MY_FUNCTION_SIGNATURE << std::endl;
  return a + b;
}

namespace internal {
void blacklisted() { std::cout << MY_FUNCTION_SIGNATURE << std::endl; }
}  // namespace internal

}  // namespace fun

int main(int, char *[]) {
  myn::MyClass().fest();
  fun::sum(3, 4);
  fun::internal::blacklisted();
  return 0;
}

Compila il codice con un qualsiasi compilatore C++ moderno che supporti C++20.

g++ -std=c++20 -o example_function test.cpp

Il risultato dell’esecuzione del programma sarà:

./example_function
# myn::MyClass::fest
# fun::sum
# -